Update from https://crrev.com/327068
This rolls in //base, //build and //sandbox/linux and updates other
things to match, in particular:
*) Update build_v8.patch
*) Add junit, mockito and roboelectric to DEPS for android test rules
*) Update DEPS for grit
*) Fix up various GN files for os->target_os rename
*) Fix up a few places that were using //base/float_util to use std::isnan
*) Fix up a few places using ApiCompatibilityUtil to use Android SDK directly
as well as a few miscellaneous fixes.
Many portions based on ncbray's work in
https://codereview.chromium.org/1108173002/
R=ncbray@chromium.org
TBR=ncbray@chromium.org
Review URL: https://codereview.chromium.org/1124763003
diff --git a/.gitignore b/.gitignore
index f3526e1..9af90fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,11 +53,14 @@
/third_party/llvm/
/third_party/llvm-build/
/third_party/lss/
+/third_party/junit/src/
/third_party/mesa/src/
+/third_party/mockito/src/
/third_party/nss/
/third_party/pdfium/
/third_party/pywebsocket/src/
/third_party/requests/src/
+/third_party/robolectric/src/
/third_party/sfntly/cpp/
/third_party/skia/
/third_party/smhasher/src/
diff --git a/DEPS b/DEPS
index d02c0ab..b16c545 100644
--- a/DEPS
+++ b/DEPS
@@ -24,14 +24,14 @@
'skia_revision': '409fd66a5afcef5f165f7ccec7c3473add231752',
'v8_revision': '230d131d173ab2d60291d303177bc04ec3f6e519',
'angle_revision': 'bdd419f9f5b006e913606e7363125942c8ae06bc',
- 'buildtools_revision': '3b302fef93f7cc58d9b8168466905237484b2772',
+ 'buildtools_revision': '15308f469a704c45d15567fa69cd94ce07ad0e1b',
'dart_revision': '45304',
'dart_observatory_packages_revision': '43830',
'pdfium_revision': 'b0115665b0f33971f1b7077740d51e155583cec0',
'boringssl_revision': '642f1498d056dbba3e50ed5a232ab2f482626dec',
'lss_revision': 'e079768b7e3a94dcbe7d338496c0c3bde7151b6e',
'nss_revision': 'bb4e75a43d007518ae7d618665ea2f25b0c60b63',
- 'nacl_revision': '19f11aa481261f38f2a1e9a04e41a7e12aa70e32',
+ 'nacl_revision': '87d5dd90911a0657c27574f78e86b7dfc4ad8b29',
}
# Only these hosts are allowed for dependencies in this DEPS file.
@@ -60,7 +60,7 @@
Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '7c81740601355556e630da515b74d889ba2f8d08',
'src/tools/grit':
- Var('chromium_git') + '/external/grit-i18n.git' + '@' + '0287c187b11ed53590254e4d817e836a44a7a1a7', # from svn revision 186
+ Var('chromium_git') + '/external/grit-i18n.git' + '@' + 'c1b1591a05209c1ad467e845ba8543c22f9072af', # from svn revision 189
'src/v8':
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
@@ -134,6 +134,15 @@
'src/third_party/jsr-305/src':
Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
+ 'src/third_party/junit/src':
+ Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1',
+
+ 'src/third_party/mockito/src':
+ Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'ed99a52e94a84bd7c467f2443b475a22fcc6ba8e',
+
+ 'src/third_party/robolectric/lib':
+ Var('chromium_git') + '/chromium/third_party/robolectric.git' + '@' + '6b63c99a8b6967acdb42cbed0adb067c80efc810',
+
'src/third_party/android_tools':
Var('chromium_git') + '/android_tools.git' + '@' + 'a1ffd63322c438627d78ea56eb73fb8779e06950',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8b9b5bf..2db7261 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -13,6 +13,18 @@
defines = [ "BASE_IMPLEMENTATION" ]
}
+if (is_win) {
+ # This is in a separate config so the flags can be applied to dependents.
+ # ldflags in GN aren't automatically inherited.
+ config("base_win_linker_flags") {
+ ldflags = [
+ "/DELAYLOAD:cfgmgr32.dll",
+ "/DELAYLOAD:powrprof.dll",
+ "/DELAYLOAD:setupapi.dll",
+ ]
+ }
+}
+
source_set("base_paths") {
sources = [
"base_paths.cc",
@@ -79,6 +91,8 @@
"android/important_file_writer_android.h",
"android/java_handler_thread.cc",
"android/java_handler_thread.h",
+ "android/java_runtime.cc",
+ "android/java_runtime.h",
"android/jni_android.cc",
"android/jni_android.h",
"android/jni_array.cc",
@@ -104,6 +118,8 @@
"android/path_utils.h",
"android/record_histogram.cc",
"android/record_histogram.h",
+ "android/record_user_action.cc",
+ "android/record_user_action.h",
"android/scoped_java_ref.cc",
"android/scoped_java_ref.h",
"android/sys_utils.cc",
@@ -149,8 +165,8 @@
"callback_internal.cc",
"callback_internal.h",
"cancelable_callback.h",
- "chromeos/memory_pressure_observer_chromeos.cc",
- "chromeos/memory_pressure_observer_chromeos.h",
+ "chromeos/memory_pressure_monitor_chromeos.cc",
+ "chromeos/memory_pressure_monitor_chromeos.h",
"command_line.cc",
"command_line.h",
"compiler_specific.h",
@@ -217,7 +233,6 @@
"files/scoped_file.h",
"files/scoped_temp_dir.cc",
"files/scoped_temp_dir.h",
- "float_util.h",
"format_macros.h",
"gtest_prod_util.h",
"guid.cc",
@@ -320,6 +335,7 @@
"message_loop/message_pump_win.h",
"move.h",
"native_library.h",
+ "native_library_ios.mm",
"native_library_mac.mm",
"native_library_posix.cc",
"native_library_win.cc",
@@ -366,6 +382,8 @@
"power_monitor/power_observer.h",
"profiler/alternate_timer.cc",
"profiler/alternate_timer.h",
+ "profiler/native_stack_sampler.cc",
+ "profiler/native_stack_sampler.h",
"profiler/scoped_profile.cc",
"profiler/scoped_profile.h",
"profiler/scoped_tracker.cc",
@@ -480,6 +498,8 @@
"third_party/dmg_fp/g_fmt.cc",
"third_party/icu/icu_utf.cc",
"third_party/icu/icu_utf.h",
+ "third_party/nspr/prtime.cc",
+ "third_party/nspr/prtime.h",
"third_party/superfasthash/superfasthash.c",
"thread_task_runner_handle.cc",
"thread_task_runner_handle.h",
@@ -623,7 +643,6 @@
":base_static",
"//base/allocator:allocator_extension_thunks",
"//base/third_party/dynamic_annotations",
- "//base/third_party/nspr",
"//third_party/modp_b64",
]
@@ -731,11 +750,7 @@
"powrprof.lib",
"setupapi.lib",
]
- ldflags = [
- "/DELAYLOAD:cfgmgr32.dll",
- "/DELAYLOAD:powrprof.dll",
- "/DELAYLOAD:setupapi.dll",
- ]
+ all_dependent_configs = [ ":base_win_linker_flags" ]
} else if (!is_nacl) {
# Non-Windows.
deps += [ "//third_party/libevent" ]
@@ -881,7 +896,7 @@
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
-if (is_linux && !is_chromeos) {
+if (is_win || (is_linux && !is_chromeos)) {
# TODO(GYP): Figure out which of these work and are needed on other platforms.
test("base_perftests") {
sources = [
@@ -899,7 +914,7 @@
]
if (is_android) {
- deps += [ "//testing/android:native_test_native_code" ]
+ deps += [ "//testing/android/native_test:native_test_native_code" ]
}
}
@@ -938,7 +953,7 @@
}
}
-source_set("prefs") {
+component("prefs") {
sources = [
"prefs/base_prefs_export.h",
"prefs/default_pref_store.cc",
@@ -1026,17 +1041,6 @@
]
}
-# TODO(pasko): Remove this target when crbug.com/424562 is fixed.
-source_set("protect_file_posix") {
- sources = [
- "files/protect_file_posix.cc",
- ]
-
- deps = [
- "//base",
- ]
-}
-
if (is_win) {
# Target to manually rebuild pe_image_test.dll which is checked into
# base/test/data/pe_image.
@@ -1082,7 +1086,7 @@
"callback_unittest.cc",
"callback_unittest.nc",
"cancelable_callback_unittest.cc",
- "chromeos/memory_pressure_observer_chromeos_unittest.cc",
+ "chromeos/memory_pressure_monitor_chromeos_unittest.cc",
"command_line_unittest.cc",
"containers/adapters_unittest.cc",
"containers/hash_tables_unittest.cc",
@@ -1102,6 +1106,7 @@
"file_version_info_unittest.cc",
"files/dir_reader_posix_unittest.cc",
"files/file_path_unittest.cc",
+ "files/file_path_watcher_unittest.cc",
"files/file_proxy_unittest.cc",
"files/file_unittest.cc",
"files/file_util_proxy_unittest.cc",
@@ -1169,6 +1174,7 @@
"metrics/sample_vector_unittest.cc",
"metrics/sparse_histogram_unittest.cc",
"metrics/statistics_recorder_unittest.cc",
+ "move_unittest.cc",
"numerics/safe_numerics_unittest.cc",
"observer_list_unittest.cc",
"os_compat_android_unittest.cc",
@@ -1236,6 +1242,7 @@
"test/histogram_tester_unittest.cc",
"test/test_reg_util_win_unittest.cc",
"test/trace_event_analyzer_unittest.cc",
+ "test/user_action_tester_unittest.cc",
"threading/non_thread_safe_unittest.cc",
"threading/platform_thread_unittest.cc",
"threading/sequenced_worker_pool_unittest.cc",
@@ -1292,7 +1299,6 @@
"//base/test:run_all_unittests",
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
- "//base/third_party/nspr",
"//base/trace_event:trace_event_unittests",
"//testing/gmock",
"//testing/gtest",
@@ -1339,6 +1345,8 @@
if (is_linux) {
sources -= [ "file_version_info_unittest.cc" ]
sources += [ "nix/xdg_util_unittest.cc" ]
+ deps += [ "//base/test:malloc_wrapper" ]
+
if (use_glib) {
configs += [ "//build/config/linux:glib" ]
}
@@ -1354,7 +1362,7 @@
}
if (is_android) {
- deps += [ "//testing/android:native_test_native_code" ]
+ deps += [ "//testing/android/native_test:native_test_native_code" ]
set_sources_assignment_filter([])
sources += [ "debug/proc_maps_linux_unittest.cc" ]
set_sources_assignment_filter(sources_assignment_filter)
@@ -1390,10 +1398,22 @@
"android/java/src/org/chromium/base/TraceEvent.java",
"android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
"android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+ "android/java/src/org/chromium/base/metrics/RecordUserAction.java",
]
+
+ deps = [
+ ":android_runtime_jni_headers",
+ ]
+
jni_package = "base"
}
+ # GYP: //base.gyp:android_runtime_jni_headers
+ generate_jar_jni("android_runtime_jni_headers") {
+ jni_package = "base"
+ classes = [ "java/lang/Runtime.class" ]
+ }
+
# GYP: //base.gyp:base_java
android_library("base_java") {
srcjar_deps = [
@@ -1432,6 +1452,15 @@
DEPRECATED_java_in_dir = "test/android/javatests/src"
}
+ # GYP: //base.gyp:base_junit_tests
+ junit_binary("base_junit_tests") {
+ java_files = [ "android/junit/src/org/chromium/base/LogTest.java" ]
+ deps = [
+ ":base_java",
+ ":base_java_test_support",
+ ]
+ }
+
# GYP: //base.gyp:base_java_application_state
# GYP: //base.gyp:base_java_library_load_from_apk_status_codes
# GYP: //base.gyp:base_java_library_process_type
diff --git a/base/OWNERS b/base/OWNERS
index 5d3e38b..9890491 100644
--- a/base/OWNERS
+++ b/base/OWNERS
@@ -1,6 +1,5 @@
mark@chromium.org
darin@chromium.org
-ajwong@chromium.org
thakis@chromium.org
danakj@chromium.org
rvargas@chromium.org
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc
index 7439d3c..43ba635 100644
--- a/base/android/base_jni_registrar.cc
+++ b/base/android/base_jni_registrar.cc
@@ -14,6 +14,7 @@
#include "base/android/field_trial_list.h"
#include "base/android/important_file_writer_android.h"
#include "base/android/java_handler_thread.h"
+#include "base/android/java_runtime.h"
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/android/jni_utils.h"
@@ -22,6 +23,7 @@
#include "base/android/path_service_android.h"
#include "base/android/path_utils.h"
#include "base/android/record_histogram.h"
+#include "base/android/record_user_action.h"
#include "base/android/sys_utils.h"
#include "base/android/thread_utils.h"
#include "base/android/trace_event_binding.h"
@@ -55,6 +57,8 @@
{"PathUtils", base::android::RegisterPathUtils},
{"PowerMonitor", base::RegisterPowerMonitor},
{"RecordHistogram", base::android::RegisterRecordHistogram},
+ {"RecordUserAction", base::android::RegisterRecordUserAction},
+ {"Runtime", base::android::JavaRuntime::Register},
{"SystemMessageHandler", base::MessagePumpForUI::RegisterBindings},
{"SysUtils", base::android::SysUtils::Register},
{"ThreadUtils", base::RegisterThreadUtils},
diff --git a/base/android/build_info.h b/base/android/build_info.h
index e4e84e8..9d73bdb 100644
--- a/base/android/build_info.h
+++ b/base/android/build_info.h
@@ -18,8 +18,6 @@
// This enumeration maps to the values returned by BuildInfo::sdk_int(),
// indicating the Android release associated with a given SDK version.
enum SdkVersion {
- SDK_VERSION_ICE_CREAM_SANDWICH = 14,
- SDK_VERSION_ICE_CREAM_SANDWICH_MR1 = 15,
SDK_VERSION_JELLY_BEAN = 16,
SDK_VERSION_JELLY_BEAN_MR1 = 17,
SDK_VERSION_JELLY_BEAN_MR2 = 18,
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index 71b79b1..40cb035 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -4,11 +4,9 @@
package org.chromium.base;
-import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
@@ -20,16 +18,12 @@
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
-import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
-import android.widget.ImageView;
-import android.widget.RemoteViews;
import android.widget.TextView;
/**
@@ -241,122 +235,9 @@
}
}
- /**
- * @see android.view.View#postInvalidateOnAnimation()
- */
- public static void postInvalidateOnAnimation(View view) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.postInvalidateOnAnimation();
- } else {
- view.postInvalidate();
- }
- }
-
- /**
- * @see android.view.View#postOnAnimation()
- */
- public static void postOnAnimation(View view, Runnable action) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.postOnAnimation(action);
- } else {
- view.postDelayed(action, getFrameTime());
- }
- }
-
- /**
- * @see android.view.View#postOnAnimationDelayed()
- */
- public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.postOnAnimationDelayed(action, delayMillis);
- } else {
- view.postDelayed(action, getFrameTime() + delayMillis);
- }
- }
-
- private static long getFrameTime() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- return ValueAnimator.getFrameDelay();
- } else {
- // Any reasonable fake frame delay will have to do.
- return 10;
- }
- }
-
- /**
- * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
- */
- public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
- CharSequence contentDescription) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- remoteViews.setContentDescription(viewId, contentDescription);
- } else {
- // setContentDescription() is unavailable in earlier versions.
- }
- }
-
- /**
- * @see android.app.Activity#startActivity(Intent, Bundle)
- */
- public static void startActivity(Context context, Intent intent, Bundle options) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- context.startActivity(intent, options);
- } else {
- context.startActivity(intent);
- }
- }
-
- /**
- * @see android.app.ActivityOptions#toBundle()
- */
- public static Bundle toBundle(ActivityOptions options) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- return options.toBundle();
- } else {
- return null;
- }
- }
-
// These methods have a new name, and the old name is deprecated.
/**
- * @see android.view.View#setBackground(Drawable)
- */
- @SuppressWarnings("deprecation")
- public static void setBackgroundForView(View view, Drawable drawable) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.setBackground(drawable);
- } else {
- view.setBackgroundDrawable(drawable);
- }
- }
-
- /**
- * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
- */
- @SuppressWarnings("deprecation")
- public static void removeOnGlobalLayoutListener(
- View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
- } else {
- view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
- }
- }
-
- /**
- * @see android.widget.ImageView#setImageAlpha(int)
- */
- @SuppressWarnings("deprecation")
- public static void setImageAlpha(ImageView iv, int alpha) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- iv.setImageAlpha(alpha);
- } else {
- iv.setAlpha(alpha);
- }
- }
-
- /**
* @see android.app.PendingIntent#getCreatorPackage()
*/
@SuppressWarnings("deprecation")
@@ -494,13 +375,4 @@
return res.getDrawable(id);
}
}
-
- /**
- * @see android.view.View#announceForAccessibility(CharSequence text)
- */
- public static void announceForAccessibility(View view, CharSequence text) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- view.announceForAccessibility(text);
- }
- }
}
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
index af02ea2..8c36b61 100644
--- a/base/android/java/src/org/chromium/base/ApplicationStatus.java
+++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -309,9 +309,8 @@
if (sCachedApplicationState == null) {
sCachedApplicationState = determineApplicationState();
}
+ return sCachedApplicationState.intValue();
}
-
- return sCachedApplicationState.intValue();
}
/**
diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
index 8f7d39d..2946f6f 100644
--- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
+++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
@@ -8,6 +8,7 @@
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
+import android.view.KeyEvent;
import android.view.Window;
/**
@@ -47,6 +48,17 @@
listener.onWindowFocusChanged(activity, hasFocus);
}
}
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals
+ // KEYCODE_MENU. (see b/20529185)
+ if (event.getKeyCode() == KeyEvent.KEYCODE_MENU
+ && activity.dispatchKeyEvent(event)) {
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
});
}
diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java
new file mode 100644
index 0000000..99d755d
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/Log.java
@@ -0,0 +1,357 @@
+// 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.
+
+package org.chromium.base;
+
+import android.text.TextUtils;
+
+import org.chromium.base.annotations.NoSideEffects;
+
+import java.util.Locale;
+
+/**
+ * Utility class for Logging.
+ *
+ * <p>
+ * Defines logging access points for each feature. They format and forward the logs to
+ * {@link android.util.Log}, allowing to standardize the output, to make it easy to identify
+ * the origin of logs, and enable or disable logging in different parts of the code.
+ * </p>
+ * <p>
+ * Please make use of the formatting capability of the logging methods rather than doing
+ * concatenations in the calling code. In the release builds of Chrome, debug and verbose log
+ * calls will be stripped out of the binary. Concatenations and method calls however will still
+ * remain and be executed. If they can't be avoided, try to generate the logs in a method annotated
+ * with {@link NoSideEffects}. Another possibility is to use
+ * {@link android.util.Log#isLoggable(String, int)}, with {@link Log#makeTag(String)} to get the
+ * correct tag.
+ * </p>
+ *
+ * Usage:
+ * <pre>
+ * private void myMethod(String awesome) {
+ * Log.i("Group", "My %s message.", awesome);
+ * Log.d("Group", "My debug message");
+ * }
+ * </pre>
+ *
+ * Logcat output:
+ * <pre>
+ * I/chromium.Group (999): My awesome message
+ * D/chromium.Group (999): [MyClass.java:42] My debug message
+ * </pre>
+ *
+ * Set the log level for a given group:
+ * <pre>
+ * $ adb shell setprop log.tag.chromium.Group VERBOSE
+ * </pre>
+ */
+public class Log {
+ private static final String BASE_TAG = "chromium";
+
+ private Log() {
+ // Static only access
+ }
+
+ /** Returns a formatted log message, using the supplied format and arguments.*/
+ private static String formatLog(String messageTemplate, Object... params) {
+ if (params != null && params.length != 0) {
+ messageTemplate = String.format(Locale.US, messageTemplate, params);
+ }
+
+ return messageTemplate;
+ }
+
+ /**
+ * Returns a formatted log message, using the supplied format and arguments.
+ * The message will be prepended with the filename and line number of the call.
+ */
+ private static String formatLogWithStack(String messageTemplate, Object... params) {
+ return "[" + getCallOrigin() + "] " + formatLog(messageTemplate, params);
+ }
+
+ /**
+ * Returns a full tag for the provided group tag. Full tags longer than 23 characters
+ * will cause a runtime exception later. (see {@link android.util.Log#isLoggable(String, int)})
+ *
+ * @param groupTag {@code null} and empty string are allowed.
+ */
+ public static String makeTag(String groupTag) {
+ if (TextUtils.isEmpty(groupTag)) return BASE_TAG;
+ return BASE_TAG + "." + groupTag;
+ }
+
+ /**
+ * Sends a {@link android.util.Log#VERBOSE} log message.
+ *
+ * For optimization purposes, only the fixed parameters versions are visible. If you need more
+ * than 7 parameters, consider building your log message using a function annotated with
+ * {@link NoSideEffects}.
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ *
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ private static void verbose(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) {
+ String message = formatLogWithStack(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.v(tag, message, tr);
+ } else {
+ android.util.Log.v(tag, message);
+ }
+ }
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 0 arg version. */
+ public static void v(String groupTag, String message) {
+ verbose(groupTag, message);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 1 arg version. */
+ public static void v(String groupTag, String messageTemplate, Object arg1) {
+ verbose(groupTag, messageTemplate, arg1);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 2 args version */
+ public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2) {
+ verbose(groupTag, messageTemplate, arg1, arg2);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 3 args version */
+ public static void v(
+ String groupTag, String messageTemplate, Object arg1, Object arg2, Object arg3) {
+ verbose(groupTag, messageTemplate, arg1, arg2, arg3);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 4 args version */
+ public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4) {
+ verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 5 args version */
+ public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5) {
+ verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 6 args version */
+ public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5, Object arg6) {
+ verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+
+ /** Sends a {@link android.util.Log#VERBOSE} log message. 7 args version */
+ public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
+ verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ }
+
+ /**
+ * Sends a {@link android.util.Log#DEBUG} log message.
+ *
+ * For optimization purposes, only the fixed parameters versions are visible. If you need more
+ * than 7 parameters, consider building your log message using a function annotated with
+ * {@link NoSideEffects}.
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ *
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ private static void debug(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) {
+ String message = formatLogWithStack(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.d(tag, message, tr);
+ } else {
+ android.util.Log.d(tag, message);
+ }
+ }
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 0 arg version. */
+ public static void d(String groupTag, String message) {
+ debug(groupTag, message);
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 1 arg version. */
+ public static void d(String groupTag, String messageTemplate, Object arg1) {
+ debug(groupTag, messageTemplate, arg1);
+ }
+ /** Sends a {@link android.util.Log#DEBUG} log message. 2 args version */
+ public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2) {
+ debug(groupTag, messageTemplate, arg1, arg2);
+ }
+ /** Sends a {@link android.util.Log#DEBUG} log message. 3 args version */
+ public static void d(
+ String groupTag, String messageTemplate, Object arg1, Object arg2, Object arg3) {
+ debug(groupTag, messageTemplate, arg1, arg2, arg3);
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 4 args version */
+ public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4) {
+ debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4);
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 5 args version */
+ public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5) {
+ debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5);
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 6 args version */
+ public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5, Object arg6) {
+ debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+
+ /** Sends a {@link android.util.Log#DEBUG} log message. 7 args version */
+ public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+ Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
+ debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ }
+
+ /**
+ * Sends an {@link android.util.Log#INFO} log message.
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ public static void i(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.INFO)) {
+ String message = formatLog(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.i(tag, message, tr);
+ } else {
+ android.util.Log.i(tag, message);
+ }
+ }
+ }
+
+ /**
+ * Sends a {@link android.util.Log#WARN} log message.
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ public static void w(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.WARN)) {
+ String message = formatLog(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.w(tag, message, tr);
+ } else {
+ android.util.Log.w(tag, message);
+ }
+ }
+ }
+
+ /**
+ * Sends an {@link android.util.Log#ERROR} log message.
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ public static void e(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) {
+ String message = formatLog(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.e(tag, message, tr);
+ } else {
+ android.util.Log.e(tag, message);
+ }
+ }
+ }
+
+ /**
+ * What a Terrible Failure: Used for conditions that should never happen, and logged at
+ * the {@link android.util.Log#ASSERT} level. Depending on the configuration, it might
+ * terminate the process.
+ *
+ * @see android.util.Log#wtf(String, String, Throwable)
+ *
+ * @param groupTag Used to identify the source of a log message. It usually refers to the
+ * package or feature, to logically group related logs.
+ * @param messageTemplate The message you would like logged. It is to be specified as a format
+ * string.
+ * @param args Arguments referenced by the format specifiers in the format string. If the last
+ * one is a {@link Throwable}, its trace will be printed.
+ */
+ public static void wtf(String groupTag, String messageTemplate, Object... args) {
+ String tag = makeTag(groupTag);
+ if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) {
+ String message = formatLog(messageTemplate, args);
+ Throwable tr = getThrowableToLog(args);
+ if (tr != null) {
+ android.util.Log.wtf(tag, message, tr);
+ } else {
+ android.util.Log.wtf(tag, message);
+ }
+ }
+ }
+
+ private static Throwable getThrowableToLog(Object[] args) {
+ if (args == null || args.length == 0) return null;
+
+ Object lastArg = args[args.length - 1];
+
+ if (!(lastArg instanceof Throwable)) return null;
+ return (Throwable) lastArg;
+ }
+
+ /** Returns a string form of the origin of the log call, to be used as secondary tag.*/
+ private static String getCallOrigin() {
+ StackTraceElement[] st = Thread.currentThread().getStackTrace();
+
+ // The call stack should look like:
+ // n [a variable number of calls depending on the vm used]
+ // +0 getCallOrigin()
+ // +1 privateLogFunction: verbose or debug
+ // +2 formatLogWithStack()
+ // +3 logFunction: v or d
+ // +4 caller
+
+ int callerStackIndex;
+ String logClassName = Log.class.getName();
+ for (callerStackIndex = 0; callerStackIndex < st.length; callerStackIndex++) {
+ if (st[callerStackIndex].getClassName().equals(logClassName)) {
+ callerStackIndex += 4;
+ break;
+ }
+ }
+
+ return st[callerStackIndex].getFileName() + ":" + st[callerStackIndex].getLineNumber();
+ }
+}
diff --git a/base/android/java/src/org/chromium/base/PackageUtils.java b/base/android/java/src/org/chromium/base/PackageUtils.java
new file mode 100644
index 0000000..ab554cd
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/PackageUtils.java
@@ -0,0 +1,37 @@
+// 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.
+
+package org.chromium.base;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+/**
+ * This class provides package checking related methods.
+ */
+public class PackageUtils {
+ /**
+ * Retrieves the version of the given package installed on the device.
+ *
+ * @param context Any context.
+ * @param packageName Name of the package to find.
+ * @return The package's version code if found, -1 otherwise.
+ */
+ public static int getPackageVersion(Context context, String packageName) {
+ int versionCode = -1;
+ PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+ if (packageInfo != null) versionCode = packageInfo.versionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ // Do nothing, versionCode stays -1
+ }
+ return versionCode;
+ }
+
+ private PackageUtils() {
+ // Hide constructor
+ }
+}
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
index d70c0cc..5da080e 100644
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -6,26 +6,58 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.os.AsyncTask;
import android.os.Environment;
+import java.util.concurrent.ExecutionException;
+
/**
* This class provides the path related methods for the native library.
*/
public abstract class PathUtils {
- private static String sDataDirectorySuffix;
+ private static final int DATA_DIRECTORY = 0;
+ private static final int DATABASE_DIRECTORY = 1;
+ private static final int CACHE_DIRECTORY = 2;
+ private static final int NUM_DIRECTORIES = 3;
+ private static AsyncTask<String, Void, String[]> sDirPathFetchTask;
// Prevent instantiation.
private PathUtils() {}
/**
- * Sets the suffix that should be used for the directory where private data is to be stored
- * by the application.
+ * Starts an asynchronous task to fetch the path of the directory where private data is to be
+ * stored by the application.
+ *
* @param suffix The private data directory suffix.
* @see Context#getDir(String, int)
*/
- public static void setPrivateDataDirectorySuffix(String suffix) {
- sDataDirectorySuffix = suffix;
+ public static void setPrivateDataDirectorySuffix(String suffix, Context context) {
+ final Context appContext = context.getApplicationContext();
+ sDirPathFetchTask = new AsyncTask<String, Void, String[]>() {
+ @Override
+ protected String[] doInBackground(String... dataDirectorySuffix) {
+ String[] paths = new String[NUM_DIRECTORIES];
+ paths[DATA_DIRECTORY] =
+ appContext.getDir(dataDirectorySuffix[0], Context.MODE_PRIVATE).getPath();
+ paths[DATABASE_DIRECTORY] = appContext.getDatabasePath("foo").getParent();
+ paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
+ return paths;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, suffix);
+ }
+
+ /**
+ * @param index The index of the cached directory path.
+ * @return The directory path requested, or null if not available.
+ */
+ private static String getDirectoryPath(int index) {
+ try {
+ return sDirPathFetchTask.get()[index];
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ return null;
}
/**
@@ -33,11 +65,8 @@
*/
@CalledByNative
public static String getDataDirectory(Context appContext) {
- if (sDataDirectorySuffix == null) {
- throw new IllegalStateException(
- "setDataDirectorySuffix must be called before getDataDirectory");
- }
- return appContext.getDir(sDataDirectorySuffix, Context.MODE_PRIVATE).getPath();
+ assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+ return getDirectoryPath(DATA_DIRECTORY);
}
/**
@@ -45,8 +74,8 @@
*/
@CalledByNative
public static String getDatabaseDirectory(Context appContext) {
- // Context.getDatabasePath() returns path for the provided filename.
- return appContext.getDatabasePath("foo").getParent();
+ assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+ return getDirectoryPath(DATABASE_DIRECTORY);
}
/**
@@ -55,7 +84,8 @@
@SuppressWarnings("unused")
@CalledByNative
public static String getCacheDirectory(Context appContext) {
- return appContext.getCacheDir().getPath();
+ assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+ return getDirectoryPath(CACHE_DIRECTORY);
}
/**
diff --git a/base/android/java/src/org/chromium/base/AccessedByNative.java b/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
similarity index 93%
rename from base/android/java/src/org/chromium/base/AccessedByNative.java
rename to base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
index 3e163fc..6df7c11 100644
--- a/base/android/java/src/org/chromium/base/AccessedByNative.java
+++ b/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.base;
+package org.chromium.base.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java b/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
similarity index 96%
rename from base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
rename to base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
index d5e9b74..c0abcbe 100644
--- a/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
+++ b/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.base;
+package org.chromium.base.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java b/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java
new file mode 100644
index 0000000..803c3f9
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java
@@ -0,0 +1,17 @@
+// 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.
+
+package org.chromium.base.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to indicate to proguard methods that have no side effects and can be
+ * safely removed if their return value is not used. This is to be used with
+ * {@link org.chromium.base.Log}'s method, that can also be removed by proguard. That way
+ * expensive calls can be left in debug builds but removed in release.
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface NoSideEffects {}
diff --git a/base/android/java/src/org/chromium/base/UsedByReflection.java b/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
similarity index 95%
rename from base/android/java/src/org/chromium/base/UsedByReflection.java
rename to base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
index 7d18fb0..a2af704 100644
--- a/base/android/java/src/org/chromium/base/UsedByReflection.java
+++ b/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.base;
+package org.chromium.base.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
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 484c6bc..7dc015d 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
@@ -14,6 +14,7 @@
import org.chromium.base.CommandLine;
import org.chromium.base.JNINamespace;
import org.chromium.base.TraceEvent;
+import org.chromium.base.VisibleForTesting;
import java.io.File;
import java.io.FileNotFoundException;
@@ -127,6 +128,7 @@
*
* @throws ProcessInitException
*/
+ @VisibleForTesting
public void ensureInitialized() throws ProcessInitException {
ensureInitialized(null, false);
}
@@ -353,9 +355,14 @@
} else {
// The library is in its own file.
Log.i(TAG, "Loading " + library);
- ApplicationInfo applicationInfo = context.getApplicationInfo();
- mLoadedFrom.put(library, new File(applicationInfo.nativeLibraryDir,
- libFilePath).getAbsolutePath());
+ if (context != null) {
+ ApplicationInfo applicationInfo = context.getApplicationInfo();
+ File file = new File(applicationInfo.nativeLibraryDir, libFilePath);
+ mLoadedFrom.put(library, file.getAbsolutePath());
+ } else {
+ Log.i(TAG, "No context, cannot locate the native library file for "
+ + library);
+ }
}
// Load the library.
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
index dbeb758..7e50998 100644
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -10,10 +10,10 @@
import android.os.Parcelable;
import android.util.Log;
-import org.chromium.base.AccessedByNative;
import org.chromium.base.CalledByNative;
import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.AccessedByNative;
import java.io.FileNotFoundException;
import java.util.HashMap;
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index c1f6d36..2f4356b 100644
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -35,7 +35,7 @@
* Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, at least 0 and at most |boundary| - 1
- * @param boundary upper bound for legal sample values - all sample values has to be strictly
+ * @param boundary upper bound for legal sample values - all sample values have to be strictly
* lower than |boundary|
*/
public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
@@ -43,13 +43,48 @@
}
/**
- * Records a sample in a count histogram of the given name. This is the Java equivalent of the
+ * Records a sample in a count histogram. This is the Java equivalent of the
* UMA_HISTOGRAM_COUNTS C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, at least 1 and at most 999999
*/
public static void recordCountHistogram(String name, int sample) {
- nativeRecordCountHistogram(name, System.identityHashCode(name), sample);
+ recordCustomCountHistogram(name, sample, 1, 1000000, 50);
+ }
+
+ /**
+ * Records a sample in a count histogram. This is the Java equivalent of the
+ * UMA_HISTOGRAM_COUNTS_100 C++ macro.
+ * @param name name of the histogram
+ * @param sample sample to be recorded, at least 1 and at most 99
+ */
+ public static void recordCount100Histogram(String name, int sample) {
+ recordCustomCountHistogram(name, sample, 1, 100, 50);
+ }
+
+ /**
+ * Records a sample in a count histogram. This is the Java equivalent of the
+ * UMA_HISTOGRAM_CUSTOM_COUNTS C++ macro.
+ * @param name name of the histogram
+ * @param sample sample to be recorded, at least |min| and at most |max| - 1
+ * @param min lower bound for expected sample values
+ * @param max upper bounds for expected sample values
+ * @param numBuckets the number of buckets
+ */
+ public static void recordCustomCountHistogram(
+ String name, int sample, int min, int max, int numBuckets) {
+ nativeRecordCustomCountHistogram(
+ name, System.identityHashCode(name), sample, min, max, numBuckets);
+ }
+
+ /**
+ * Records a sparse histogram. This is the Java equivalent of UMA_HISTOGRAM_SPARSE_SLOWLY.
+ * @param name name of the histogram
+ * @param sample sample to be recorded. All values of |sample| are valid, including negative
+ * values.
+ */
+ public static void recordSparseSlowlyHistogram(String name, int sample) {
+ nativeRecordSparseHistogram(name, System.identityHashCode(name), sample);
}
/**
@@ -133,7 +168,9 @@
private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample);
private static native void nativeRecordEnumeratedHistogram(
String name, int key, int sample, int boundary);
- private static native void nativeRecordCountHistogram(String name, int key, int sample);
+ private static native void nativeRecordCustomCountHistogram(
+ String name, int key, int sample, int min, int max, int numBuckets);
+ private static native void nativeRecordSparseHistogram(String name, int key, int sample);
private static native int nativeGetHistogramValueCountForTesting(String name, int sample);
private static native void nativeInitialize();
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
new file mode 100644
index 0000000..d7cc32c
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
@@ -0,0 +1,36 @@
+// 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.
+
+package org.chromium.base.metrics;
+
+import org.chromium.base.JNINamespace;
+import org.chromium.base.ThreadUtils;
+
+/**
+ * Java API for recording UMA actions.
+ *
+ * WARNINGS:
+ * JNI calls are relatively costly - avoid using in performance-critical code.
+ *
+ * We use a script (extract_actions.py) to scan the source code and extract actions. A string
+ * literal (not a variable) must be passed to record().
+ */
+@JNINamespace("base::android")
+public class RecordUserAction {
+ public static void record(final String action) {
+ if (ThreadUtils.runningOnUiThread()) {
+ nativeRecordUserAction(action);
+ return;
+ }
+
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ nativeRecordUserAction(action);
+ }
+ });
+ }
+
+ private static native void nativeRecordUserAction(String action);
+}
diff --git a/base/android/java_runtime.cc b/base/android/java_runtime.cc
new file mode 100644
index 0000000..5be9adf
--- /dev/null
+++ b/base/android/java_runtime.cc
@@ -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.
+
+#include "base/android/java_runtime.h"
+
+#include "jni/Runtime_jni.h"
+
+namespace base {
+namespace android {
+
+bool JavaRuntime::Register(JNIEnv* env) {
+ return JNI_Runtime::RegisterNativesImpl(env);
+}
+
+void JavaRuntime::GetMemoryUsage(long* total_memory, long* free_memory) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> runtime =
+ JNI_Runtime::Java_Runtime_getRuntime(env);
+ *total_memory = JNI_Runtime::Java_Runtime_totalMemory(env, runtime.obj());
+ *free_memory = JNI_Runtime::Java_Runtime_freeMemory(env, runtime.obj());
+}
+
+} // namespace android
+} // namespace base
diff --git a/base/android/java_runtime.h b/base/android/java_runtime.h
new file mode 100644
index 0000000..bde4c5c
--- /dev/null
+++ b/base/android/java_runtime.h
@@ -0,0 +1,28 @@
+// 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 BASE_ANDROID_JAVA_RUNTIME_H
+#define BASE_ANDROID_JAVA_RUNTIME_H
+
+#include "base/android/scoped_java_ref.h"
+#include "base/base_export.h"
+
+namespace base {
+namespace android {
+
+// Wrapper class for using the java.lang.Runtime object from jni.
+class BASE_EXPORT JavaRuntime {
+ public:
+ // Registers the jni class (once per process).
+ static bool Register(JNIEnv* env);
+
+ // Fills the total memory used and memory allocated for objects by the java
+ // heap in the current process. Returns true on success.
+ static void GetMemoryUsage(long* total_memory, long* free_memory);
+};
+
+} // namespace android
+} // namespace base
+
+#endif // BASE_ANDROID_JAVA_RUNTIME_H
diff --git a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
new file mode 100644
index 0000000..45b3e21
--- /dev/null
+++ b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
@@ -0,0 +1,71 @@
+// 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.
+
+package org.chromium.base;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.os.Build;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test of ApiCompatibilityUtils
+ */
+public class ApiCompatibilityUtilsTest extends InstrumentationTestCase {
+ private static final long WAIT_TIMEOUT_IN_MS = 5000;
+ private static final long SLEEP_INTERVAL_IN_MS = 50;
+
+ static class MockActivity extends Activity {
+ int mFinishAndRemoveTaskCallbackCount;
+ int mFinishCallbackCount;
+ boolean mIsFinishing;
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ @Override
+ public void finishAndRemoveTask() {
+ mFinishAndRemoveTaskCallbackCount++;
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) mIsFinishing = true;
+ }
+
+ @Override
+ public void finish() {
+ mFinishCallbackCount++;
+ mIsFinishing = true;
+ }
+
+ @Override
+ public boolean isFinishing() {
+ return mIsFinishing;
+ }
+ }
+
+ @SmallTest
+ public void testFinishAndRemoveTask() throws InterruptedException {
+ MockActivity activity = new MockActivity();
+ ApiCompatibilityUtils.finishAndRemoveTask(activity);
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
+ assertEquals(1, activity.mFinishAndRemoveTaskCallbackCount);
+ assertEquals(0, activity.mFinishCallbackCount);
+ } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
+ long startTime = SystemClock.uptimeMillis();
+ while (activity.mFinishCallbackCount == 0
+ && SystemClock.uptimeMillis() - startTime < WAIT_TIMEOUT_IN_MS) {
+ Thread.sleep(SLEEP_INTERVAL_IN_MS);
+ }
+
+ // MockActivity#finishAndRemoveTask() never sets isFinishing() to true for LOLLIPOP to
+ // simulate an exceptional case. In that case, MockActivity#finish() should be called
+ // after 3 tries.
+ assertEquals(3, activity.mFinishAndRemoveTaskCallbackCount);
+ assertEquals(1, activity.mFinishCallbackCount);
+ } else {
+ assertEquals(0, activity.mFinishAndRemoveTaskCallbackCount);
+ assertEquals(1, activity.mFinishCallbackCount);
+ }
+ assertTrue(activity.mIsFinishing);
+ }
+}
diff --git a/base/android/javatests/src/org/chromium/base/ObserverListTest.java b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
index 599534a..973682b 100644
--- a/base/android/javatests/src/org/chromium/base/ObserverListTest.java
+++ b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
@@ -72,8 +72,7 @@
private static <T> int getSizeOfIterable(Iterable<T> iterable) {
int num = 0;
- for (T el : iterable)
- num++;
+ for (T el : iterable) num++;
return num;
}
@@ -91,8 +90,7 @@
observerList.addObserver(a);
observerList.addObserver(b);
- for (Observer obs : observerList)
- obs.observe(10);
+ for (Observer obs : observerList) obs.observe(10);
// Removing an observer not in the list should do nothing.
observerList.removeObserver(e);
@@ -101,8 +99,7 @@
observerList.addObserver(c);
observerList.addObserver(d);
- for (Observer obs : observerList)
- obs.observe(10);
+ for (Observer obs : observerList) obs.observe(10);
// observe should be called twice on a.
assertEquals(20, a.mTotal);
@@ -129,8 +126,7 @@
observerList.addObserver(a);
observerList.addObserver(b);
- for (Observer obs : observerList)
- obs.observe(10);
+ for (Observer obs : observerList) obs.observe(10);
assertTrue(observerList.hasObserver(c));
assertEquals(10, a.mTotal);
@@ -248,7 +244,6 @@
// If we remove an object while iterating, it will be replaced by 'null'.
observerList.addObserver(a);
- Iterator<Object> iterator = observerList.iterator();
assertTrue(observerList.removeObserver(a));
assertFalse(observerList.removeObserver(null));
}
diff --git a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
index 732fe6e..89bee99 100644
--- a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
+++ b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
@@ -6,11 +6,11 @@
import android.graphics.Rect;
-import org.chromium.base.AccessedByNative;
import org.chromium.base.CalledByNative;
-import org.chromium.base.CalledByNativeUnchecked;
import org.chromium.base.JNINamespace;
import org.chromium.base.NativeClassQualifiedName;
+import org.chromium.base.annotations.AccessedByNative;
+import org.chromium.base.annotations.CalledByNativeUnchecked;
import java.util.ArrayList;
import java.util.Iterator;
diff --git a/base/android/junit/src/org/chromium/base/LogTest.java b/base/android/junit/src/org/chromium/base/LogTest.java
new file mode 100644
index 0000000..14726fe
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/LogTest.java
@@ -0,0 +1,93 @@
+// 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.
+
+package org.chromium.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowLog;
+
+import java.util.List;
+
+/** Unit tests for {@link Log}. */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {LogTest.PermissiveShadowLog.class})
+public class LogTest {
+ /** Test method for {@link Log#makeTag(String)} */
+ @Test
+ public void testMakeTag() {
+ assertEquals("chromium.Foo", Log.makeTag("Foo"));
+ assertEquals("chromium", Log.makeTag(null));
+ assertEquals("chromium", Log.makeTag(""));
+ }
+
+ /** Tests that the computed call origin is the correct one. */
+ @Test
+ public void callOriginTest() {
+ Log.d("Foo", "Bar");
+
+ List<ShadowLog.LogItem> logs = ShadowLog.getLogs();
+ assertEquals("Only one log should be written", 1, logs.size());
+
+ assertTrue("The origin of the log message (" + logs.get(0).msg + ") looks wrong.",
+ logs.get(0).msg.matches("\\[LogTest.java:\\d+\\].*"));
+ }
+
+ /** Tests that exceptions provided to the log functions are properly recognized and printed. */
+ @Test
+ public void exceptionLoggingTest() {
+ Throwable t = new Throwable() {
+ @Override
+ public String toString() {
+ return "MyThrowable";
+ }
+ };
+
+ Throwable t2 = new Throwable() {
+ @Override
+ public String toString() {
+ return "MyOtherThrowable";
+ }
+ };
+
+ List<ShadowLog.LogItem> logs = ShadowLog.getLogs();
+
+ // The throwable gets printed out
+ Log.i("Foo", "Bar", t);
+ assertEquals(t, logs.get(logs.size() - 1).throwable);
+ assertEquals("Bar", logs.get(logs.size() - 1).msg);
+
+ // The throwable can be both added to the message itself and printed out
+ Log.i("Foo", "Bar %s", t);
+ assertEquals(t, logs.get(logs.size() - 1).throwable);
+ assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
+
+ // Non throwable are properly identified
+ Log.i("Foo", "Bar %s", t, "Baz");
+ assertNull(logs.get(logs.size() - 1).throwable);
+ assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
+
+ // The last throwable is the one used that is going to be printed out
+ Log.i("Foo", "Bar %s %s", t, t2);
+ assertEquals(t2, logs.get(logs.size() - 1).throwable);
+ assertEquals("Bar MyThrowable MyOtherThrowable", logs.get(logs.size() - 1).msg);
+ }
+
+ /** Needed to allow debug/verbose logging that is disabled by default. */
+ @Implements(android.util.Log.class)
+ public static class PermissiveShadowLog extends ShadowLog {
+ @Implementation
+ public static boolean isLoggable(String tag, int level) {
+ return true;
+ }
+ }
+}
diff --git a/base/android/linker/BUILD.gn b/base/android/linker/BUILD.gn
index 4817d88..190ea47 100644
--- a/base/android/linker/BUILD.gn
+++ b/base/android/linker/BUILD.gn
@@ -5,7 +5,6 @@
import("//build/config/android/config.gni")
assert(is_android)
-assert(!is_android_webview_build)
# GYP: //base/base.gyp:chromium_android_linker
shared_library("chromium_android_linker") {
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 1a11639..b79eaf4 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -128,6 +128,50 @@
return true;
}
+// Initialize a jfieldID corresponding to the static field of a given |clazz|,
+// with name |field_name| and signature |field_sig|.
+// |env| is the current JNI environment handle.
+// On success, return true and set |*field_id|.
+bool InitStaticFieldId(JNIEnv* env,
+ jclass clazz,
+ const char* field_name,
+ const char* field_sig,
+ jfieldID* field_id) {
+ *field_id = env->GetStaticFieldID(clazz, field_name, field_sig);
+ if (!*field_id) {
+ LOG_ERROR("Could not find ID for static field '%s'", field_name);
+ return false;
+ }
+ LOG_INFO(
+ "%s: Found ID %p for static field '%s'",
+ __FUNCTION__, *field_id, field_name);
+ return true;
+}
+
+// Initialize a jint corresponding to the static integer field of a class
+// with class name |class_name| and field name |field_name|.
+// |env| is the current JNI environment handle.
+// On success, return true and set |*value|.
+bool InitStaticInt(JNIEnv* env,
+ const char* class_name,
+ const char* field_name,
+ jint* value) {
+ jclass clazz;
+ if (!InitClassReference(env, class_name, &clazz))
+ return false;
+
+ jfieldID field_id;
+ if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id))
+ return false;
+
+ *value = env->GetStaticIntField(clazz, field_id);
+ LOG_INFO(
+ "%s: Found value %d for class '%s', static field '%s'",
+ __FUNCTION__, *value, class_name, field_name);
+
+ return true;
+}
+
// A class used to model the field IDs of the org.chromium.base.Linker
// LibInfo inner class, used to communicate data with the Java side
// of the linker.
@@ -190,6 +234,23 @@
static LibInfo_class s_lib_info_fields;
+// Retrieve the SDK build version and pass it into the crazy linker. This
+// needs to be done early in initialization, before any other crazy linker
+// code is run.
+// |env| is the current JNI environment handle.
+// On success, return true.
+bool InitSDKVersionInfo(JNIEnv* env) {
+ jint value = 0;
+ if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value))
+ return false;
+
+ crazy_set_sdk_build_version(static_cast<int>(value));
+ LOG_INFO("%s: Set SDK build version to %d",
+ __FUNCTION__, static_cast<int>(value));
+
+ return true;
+}
+
// The linker uses a single crazy_context_t object created on demand.
// There is no need to protect this against concurrent access, locking
// is already handled on the Java side.
@@ -758,6 +819,11 @@
return -1;
}
+ // Initialize SDK version info.
+ LOG_INFO("%s: Retrieving SDK version info", __FUNCTION__);
+ if (!InitSDKVersionInfo(env))
+ return -1;
+
// Register native methods.
jclass linker_class;
if (!InitClassReference(env,
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
index 8b7f7bd..9a68dec 100644
--- a/base/android/record_histogram.cc
+++ b/base/android/record_histogram.cc
@@ -10,6 +10,7 @@
#include "base/android/jni_string.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
@@ -60,28 +61,42 @@
return InsertLocked(j_histogram_key, histogram);
}
- HistogramBase* CountHistogram(JNIEnv* env,
- jstring j_histogram_name,
- jint j_histogram_key) {
- // These values are based on the hard-coded constants in the
- // UMA_HISTOGRAM_COUNTS macro from base/metrics/histogram_macros.h.
- const int histogram_min = 1;
- const int histogram_max = 1000000;
- const int histogram_num_buckets = 50;
-
+ HistogramBase* CustomCountHistogram(JNIEnv* env,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jint j_min,
+ jint j_max,
+ jint j_num_buckets) {
DCHECK(j_histogram_name);
DCHECK(j_histogram_key);
+ int64 min = static_cast<int64>(j_min);
+ int64 max = static_cast<int64>(j_max);
+ int num_buckets = static_cast<int>(j_num_buckets);
HistogramBase* histogram = FindLocked(j_histogram_key);
if (histogram) {
- DCHECK(histogram->HasConstructionArguments(histogram_min, histogram_max,
- histogram_num_buckets));
+ DCHECK(histogram->HasConstructionArguments(min, max, num_buckets));
return histogram;
}
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram = Histogram::FactoryGet(histogram_name, histogram_min,
- histogram_max, histogram_num_buckets,
- HistogramBase::kUmaTargetedHistogramFlag);
+ histogram =
+ Histogram::FactoryGet(histogram_name, min, max, num_buckets,
+ HistogramBase::kUmaTargetedHistogramFlag);
+ return InsertLocked(j_histogram_key, histogram);
+ }
+
+ HistogramBase* SparseHistogram(JNIEnv* env,
+ jstring j_histogram_name,
+ jint j_histogram_key) {
+ DCHECK(j_histogram_name);
+ DCHECK(j_histogram_key);
+ HistogramBase* histogram = FindLocked(j_histogram_key);
+ if (histogram)
+ return histogram;
+
+ std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
+ histogram = SparseHistogram::FactoryGet(
+ histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
return InsertLocked(j_histogram_key, histogram);
}
@@ -158,18 +173,33 @@
->Add(sample);
}
-void RecordCountHistogram(JNIEnv* env,
- jclass clazz,
- jstring j_histogram_name,
- jint j_histogram_key,
- jint j_sample) {
+void RecordCustomCountHistogram(JNIEnv* env,
+ jclass clazz,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jint j_sample,
+ jint j_min,
+ jint j_max,
+ jint j_num_buckets) {
int sample = static_cast<int>(j_sample);
g_histograms.Get()
- .CountHistogram(env, j_histogram_name, j_histogram_key)
+ .CustomCountHistogram(env, j_histogram_name, j_histogram_key, j_min,
+ j_max, j_num_buckets)
->Add(sample);
}
+void RecordSparseHistogram(JNIEnv* env,
+ jclass clazz,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jint j_sample) {
+ int sample = static_cast<int>(j_sample);
+ g_histograms.Get()
+ .SparseHistogram(env, j_histogram_name, j_histogram_key)
+ ->Add(sample);
+}
+
void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
jclass clazz,
jstring j_histogram_name,
diff --git a/base/android/record_user_action.cc b/base/android/record_user_action.cc
new file mode 100644
index 0000000..6172f2e
--- /dev/null
+++ b/base/android/record_user_action.cc
@@ -0,0 +1,24 @@
+// 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/android/record_user_action.h"
+
+#include "base/android/jni_string.h"
+#include "base/metrics/user_metrics.h"
+#include "jni/RecordUserAction_jni.h"
+
+namespace base {
+namespace android {
+
+static void RecordUserAction(JNIEnv* env, jclass clazz, jstring j_action) {
+ RecordComputedAction(ConvertJavaStringToUTF8(env, j_action));
+}
+
+// Register native methods
+bool RegisterRecordUserAction(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace base
diff --git a/base/android/record_user_action.h b/base/android/record_user_action.h
new file mode 100644
index 0000000..2c2b854
--- /dev/null
+++ b/base/android/record_user_action.h
@@ -0,0 +1,19 @@
+// 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 BASE_ANDROID_RECORD_USER_ACTION_H_
+#define BASE_ANDROID_RECORD_USER_ACTION_H_
+
+#include <jni.h>
+
+namespace base {
+namespace android {
+
+// Registers the native methods through jni
+bool RegisterRecordUserAction(JNIEnv* env);
+
+} // namespace android
+} // namespace base
+
+#endif // BASE_ANDROID_RECORD_USER_ACTION_H_
diff --git a/base/async_socket_io_handler.h b/base/async_socket_io_handler.h
index bedb00f..a22c29d 100644
--- a/base/async_socket_io_handler.h
+++ b/base/async_socket_io_handler.h
@@ -76,9 +76,9 @@
private:
#if defined(OS_WIN)
// Implementation of IOHandler on Windows.
- virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
- DWORD bytes_transfered,
- DWORD error) override;
+ void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
+ DWORD bytes_transfered,
+ DWORD error) override;
#elif defined(OS_POSIX)
// Implementation of base::MessageLoopForIO::Watcher.
void OnFileCanWriteWithoutBlocking(int socket) override {}
diff --git a/base/base.gyp b/base/base.gyp
index ac37a89..e9d3e81 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -103,7 +103,9 @@
}],
],
'dependencies': [
+ 'base_java',
'base_jni_headers',
+ '../build/android/ndk.gyp:cpu_features',
'../third_party/ashmem/ashmem.gyp:ashmem',
],
'link_settings': {
@@ -114,14 +116,6 @@
'sources!': [
'debug/stack_trace_posix.cc',
],
- 'includes': [
- '../build/android/cpufeatures.gypi',
- ],
- }],
- ['OS == "android" and _toolset == "target" and android_webview_build == 0', {
- 'dependencies': [
- 'base_java',
- ],
}],
['os_bsd==1', {
'include_dirs': [
@@ -196,6 +190,9 @@
],
},
],
+ 'dependencies': [
+ 'trace_event/etw_manifest/etw_manifest.gyp:etw_manifest',
+ ],
}],
['OS == "mac" or (OS == "ios" and _toolset == "host")', {
'link_settings': {
@@ -379,24 +376,6 @@
],
},
{
- # TODO(pasko): Remove this target when crbug.com/424562 is fixed.
- # GN: //base:protect_file_posix
- 'target_name': 'protect_file_posix',
- 'conditions': [
- ['os_posix == 1', {
- 'type': 'static_library',
- 'dependencies': [
- 'base',
- ],
- 'sources': [
- 'files/protect_file_posix.cc',
- ],
- }, {
- 'type': 'none',
- }],
- ],
- },
- {
'target_name': 'base_prefs_test_support',
'type': 'static_library',
'dependencies': [
@@ -478,7 +457,7 @@
'callback_unittest.cc',
'callback_unittest.nc',
'cancelable_callback_unittest.cc',
- 'chromeos/memory_pressure_observer_chromeos_unittest.cc',
+ 'chromeos/memory_pressure_monitor_chromeos_unittest.cc',
'command_line_unittest.cc',
'containers/adapters_unittest.cc',
'containers/hash_tables_unittest.cc',
@@ -498,6 +477,7 @@
'file_version_info_unittest.cc',
'files/dir_reader_posix_unittest.cc',
'files/file_path_unittest.cc',
+ 'files/file_path_watcher_unittest.cc',
'files/file_proxy_unittest.cc',
'files/file_unittest.cc',
'files/file_util_proxy_unittest.cc',
@@ -569,6 +549,7 @@
'metrics/sample_vector_unittest.cc',
'metrics/sparse_histogram_unittest.cc',
'metrics/statistics_recorder_unittest.cc',
+ 'move_unittest.cc',
'numerics/safe_numerics_unittest.cc',
'observer_list_unittest.cc',
'os_compat_android_unittest.cc',
@@ -637,6 +618,7 @@
'test/test_pending_task_unittest.cc',
'test/test_reg_util_win_unittest.cc',
'test/trace_event_analyzer_unittest.cc',
+ 'test/user_action_tester_unittest.cc',
'threading/non_thread_safe_unittest.cc',
'threading/platform_thread_unittest.cc',
'threading/sequenced_worker_pool_unittest.cc',
@@ -762,11 +744,17 @@
'message_loop/message_pump_glib_unittest.cc',
]
}],
- ['OS == "linux" and use_allocator!="none"', {
- 'dependencies': [
- 'allocator/allocator.gyp:allocator',
- ],
- },
+ ['OS == "linux"', {
+ 'dependencies': [
+ 'malloc_wrapper',
+ ],
+ 'conditions': [
+ ['use_allocator!="none"', {
+ 'dependencies': [
+ 'allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ]},
],
['OS == "win"', {
'sources!': [
@@ -797,14 +785,6 @@
'../third_party/icu/icu.gyp:icudata',
],
}],
- ['incremental_chrome_dll', {
- 'defines': [
- # Used only to workaround a linker bug, do not use this
- # otherwise, and don't make it broader scope. See
- # http://crbug.com/251251.
- 'INCREMENTAL_LINKING',
- ],
- }],
],
}, { # OS != "win"
'dependencies': [
@@ -924,6 +904,8 @@
'test/gtest_xml_util.h',
'test/histogram_tester.cc',
'test/histogram_tester.h',
+ 'test/ios/wait_util.h',
+ 'test/ios/wait_util.mm',
'test/launcher/test_launcher.cc',
'test/launcher/test_launcher.h',
'test/launcher/test_result.cc',
@@ -937,6 +919,8 @@
'test/mock_chrome_application_mac.mm',
'test/mock_devices_changed_observer.cc',
'test/mock_devices_changed_observer.h',
+ 'test/mock_entropy_provider.cc',
+ 'test/mock_entropy_provider.h',
'test/mock_log.cc',
'test/mock_log.h',
'test/multiprocess_test.cc',
@@ -1007,6 +991,8 @@
'test/trace_event_analyzer.h',
'test/trace_to_file.cc',
'test/trace_to_file.h',
+ 'test/user_action_tester.cc',
+ 'test/user_action_tester.h',
'test/values_test_util.cc',
'test/values_test_util.h',
],
@@ -1109,6 +1095,7 @@
'allocator/allocator.gyp:allocator_extension_thunks_win64',
'../third_party/modp_b64/modp_b64.gyp:modp_b64_win64',
'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+ 'trace_event/etw_manifest/etw_manifest.gyp:etw_manifest',
],
# TODO(gregoryd): direct_dependent_settings should be shared with the
# 32-bit target, but it doesn't work due to a bug in gyp
@@ -1329,6 +1316,20 @@
},
],
}],
+ ['OS == "linux"', {
+ 'targets': [
+ {
+ 'target_name': 'malloc_wrapper',
+ 'type': 'shared_library',
+ 'dependencies': [
+ 'base',
+ ],
+ 'sources': [
+ 'test/malloc_wrapper.cc',
+ ],
+ }
+ ],
+ }],
['OS == "android"', {
'targets': [
{
@@ -1358,13 +1359,27 @@
'android/java/src/org/chromium/base/TraceEvent.java',
'android/java/src/org/chromium/base/library_loader/LibraryLoader.java',
'android/java/src/org/chromium/base/metrics/RecordHistogram.java',
+ 'android/java/src/org/chromium/base/metrics/RecordUserAction.java',
],
'variables': {
'jni_gen_package': 'base',
},
+ 'dependencies': [
+ 'android_runtime_jni_headers',
+ ],
'includes': [ '../build/jni_generator.gypi' ],
},
{
+ # GN: //base:android_runtime_jni_headers
+ 'target_name': 'android_runtime_jni_headers',
+ 'type': 'none',
+ 'variables': {
+ 'jni_gen_package': 'base',
+ 'input_java_class': 'java/lang/Runtime.class',
+ },
+ 'includes': [ '../build/jar_file_jni_generator.gypi' ],
+ },
+ {
# TODO(GN)
'target_name': 'base_unittests_jni_headers',
'type': 'none',
@@ -1412,15 +1427,9 @@
'base_java_library_process_type',
'base_java_memory_pressure_level',
'base_native_libraries_gen',
+ '../third_party/jsr-305/jsr-305.gyp:jsr_305_javalib',
],
'includes': [ '../build/java.gypi' ],
- 'conditions': [
- ['android_webview_build==0', {
- 'dependencies': [
- '../third_party/jsr-305/jsr-305.gyp:jsr_305_javalib',
- ],
- }]
- ],
},
{
# GN: //base:base_java_unittest_support
@@ -1474,6 +1483,23 @@
'includes': [ '../build/java.gypi' ],
},
{
+ # GN: //base:base_junit_tests
+ 'target_name': 'base_junit_tests',
+ 'type': 'none',
+ 'dependencies': [
+ 'base_java',
+ 'base_java_test_support',
+ '../testing/android/junit/junit_test.gyp:junit_test_support',
+ ],
+ 'variables': {
+ 'main_class': 'org.chromium.testing.local.JunitTestMain',
+ 'src_paths': [
+ '../base/android/junit/',
+ ],
+ },
+ 'includes': [ '../build/host_jar.gypi' ],
+ },
+ {
# GN: //base:base_javatests
'target_name': 'base_javatests',
'type': 'none',
@@ -1490,25 +1516,18 @@
# GN: //base/android/linker:chromium_android_linker
'target_name': 'chromium_android_linker',
'type': 'shared_library',
- 'conditions': [
- # Avoid breaking the webview build because it
- # does not have <(android_ndk_root)/crazy_linker.gyp.
- # Note that webview never uses the linker anyway.
- ['android_webview_build == 0', {
- 'sources': [
- 'android/linker/linker_jni.cc',
- ],
- # The crazy linker is never instrumented.
- 'cflags!': [
- '-finstrument-functions',
- ],
- 'dependencies': [
- # The NDK contains the crazy_linker here:
- # '<(android_ndk_root)/crazy_linker.gyp:crazy_linker'
- # However, we use our own fork. See bug 384700.
- '../third_party/android_crazy_linker/crazy_linker.gyp:crazy_linker',
- ],
- }],
+ 'sources': [
+ 'android/linker/linker_jni.cc',
+ ],
+ # The crazy linker is never instrumented.
+ 'cflags!': [
+ '-finstrument-functions',
+ ],
+ 'dependencies': [
+ # The NDK contains the crazy_linker here:
+ # '<(android_ndk_root)/crazy_linker.gyp:crazy_linker'
+ # However, we use our own fork. See bug 384700.
+ '../third_party/android_crazy_linker/crazy_linker.gyp:crazy_linker',
],
},
{
diff --git a/base/base.gypi b/base/base.gypi
index 825bca1..bbc3f60 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -45,6 +45,8 @@
'android/important_file_writer_android.h',
'android/java_handler_thread.cc',
'android/java_handler_thread.h',
+ 'android/java_runtime.cc',
+ 'android/java_runtime.h',
'android/jni_android.cc',
'android/jni_android.h',
'android/jni_array.cc',
@@ -70,6 +72,8 @@
'android/path_utils.h',
'android/record_histogram.cc',
'android/record_histogram.h',
+ 'android/record_user_action.cc',
+ 'android/record_user_action.h',
'android/scoped_java_ref.cc',
'android/scoped_java_ref.h',
'android/sys_utils.cc',
@@ -122,8 +126,8 @@
'callback_internal.h',
'callback_list.h',
'cancelable_callback.h',
- 'chromeos/memory_pressure_observer_chromeos.cc',
- 'chromeos/memory_pressure_observer_chromeos.h',
+ 'chromeos/memory_pressure_monitor_chromeos.cc',
+ 'chromeos/memory_pressure_monitor_chromeos.h',
'command_line.cc',
'command_line.h',
'compiler_specific.h',
@@ -223,7 +227,6 @@
'files/scoped_file.h',
'files/scoped_temp_dir.cc',
'files/scoped_temp_dir.h',
- 'float_util.h',
'format_macros.h',
'gtest_prod_util.h',
'guid.cc',
@@ -329,6 +332,8 @@
'memory/manual_constructor.h',
'memory/memory_pressure_listener.cc',
'memory/memory_pressure_listener.h',
+ 'memory/memory_pressure_monitor.cc',
+ 'memory/memory_pressure_monitor.h',
'memory/raw_scoped_refptr_mismatch_checker.h',
'memory/ref_counted.cc',
'memory/ref_counted.h',
@@ -391,6 +396,7 @@
'metrics/user_metrics_action.h',
'move.h',
'native_library.h',
+ 'native_library_ios.mm',
'native_library_mac.mm',
'native_library_posix.cc',
'native_library_win.cc',
@@ -484,6 +490,8 @@
'process/process_win.cc',
'profiler/alternate_timer.cc',
'profiler/alternate_timer.h',
+ 'profiler/native_stack_sampler.cc',
+ 'profiler/native_stack_sampler.h',
'profiler/scoped_profile.cc',
'profiler/scoped_profile.h',
'profiler/scoped_tracker.cc',
@@ -836,13 +844,6 @@
['include', '^threading/platform_thread_linux\\.cc$'],
],
}],
- ['OS == "android" and <(android_webview_build)==1', {
- 'defines': [
- # WebView builds as part of the system which already has sincos;
- # avoid defining it again as it causes a linker warning.
- 'ANDROID_SINCOS_PROVIDED',
- ],
- }],
['<(chromeos) == 1', {
'sources!': [
'power_monitor/power_monitor_device_source_posix.cc',
@@ -876,6 +877,7 @@
['include', '^process/.*_ios\.(cc|mm)$'],
['include', '^process/memory_stubs\.cc$'],
['include', '^process/process_handle_posix\.cc$'],
+ ['include', '^process/process_metrics\\.cc$'],
['exclude', '^threading/platform_thread_internal_posix\\.(h|cc)'],
['exclude', 'files/file_path_watcher_fsevents.cc'],
['exclude', 'files/file_path_watcher_fsevents.h'],
diff --git a/base/base.isolate b/base/base.isolate
index a245819..c7ba651 100644
--- a/base/base.isolate
+++ b/base/base.isolate
@@ -7,6 +7,8 @@
# itself, virtually all targets using it has to include icu. The only
# exception is the Windows sandbox (?).
'../third_party/icu/icu.isolate',
+ # Sanitizer-instrumented third-party libraries (if enabled).
+ '../third_party/instrumented_libraries/instrumented_libraries.isolate',
],
'conditions': [
['use_custom_libcxx==1', {
@@ -16,13 +18,6 @@
],
},
}],
- ['use_instrumented_libraries==1', {
- 'variables': {
- 'files': [
- '<(PRODUCT_DIR)/instrumented_libraries/',
- ],
- },
- }],
['OS=="mac" and asan==1', {
'variables': {
'files': [
diff --git a/base/base_nacl.gyp b/base/base_nacl.gyp
index 90a2893..40005d2 100644
--- a/base/base_nacl.gyp
+++ b/base/base_nacl.gyp
@@ -39,9 +39,6 @@
'-fno-strict-aliasing',
],
},
- 'dependencies': [
- '../native_client/tools.gyp:prep_toolchain',
- ],
},
{
'target_name': 'base_i18n_nacl',
@@ -63,7 +60,6 @@
],
},
'dependencies': [
- '../native_client/tools.gyp:prep_toolchain',
'../third_party/icu/icu_nacl.gyp:icudata_nacl',
'../third_party/icu/icu_nacl.gyp:icui18n_nacl',
'../third_party/icu/icu_nacl.gyp:icuuc_nacl',
@@ -113,7 +109,6 @@
'rand_util_nacl.cc',
],
'dependencies': [
- '../native_client/tools.gyp:prep_toolchain',
'../third_party/libevent/libevent_nacl_nonsfi.gyp:event_nacl_nonsfi',
],
},
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index e329152..b1c270c 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -50,6 +50,13 @@
'read_only': 1,
},
}],
+ ['OS=="linux"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/lib/libmalloc_wrapper.so',
+ ],
+ },
+ }],
['OS=="mac" and asan==1 and fastbuild==0', {
'variables': {
'files': [
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index a30b775..f885403 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -778,10 +778,10 @@
copies = 0;
assigns = 0;
- DerivedCopyCounter dervied(&copies, &assigns);
+ DerivedCopyCounter derived(&copies, &assigns);
Callback<void(CopyCounter)> coerce_cb =
Bind(&VoidPolymorphic1<CopyCounter>);
- coerce_cb.Run(CopyCounter(dervied));
+ coerce_cb.Run(CopyCounter(derived));
EXPECT_GE(2, copies);
EXPECT_EQ(0, assigns);
}
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_monitor_chromeos.cc
similarity index 68%
rename from base/chromeos/memory_pressure_observer_chromeos.cc
rename to base/chromeos/memory_pressure_monitor_chromeos.cc
index 5691eb8..404c515 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.cc
+++ b/base/chromeos/memory_pressure_monitor_chromeos.cc
@@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/chromeos/memory_pressure_observer_chromeos.h"
+#include "base/chromeos/memory_pressure_monitor_chromeos.h"
+
+#include <fcntl.h>
+#include <sys/select.h>
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
+#include "base/posix/eintr_wrapper.h"
#include "base/process/process_metrics.h"
#include "base/time/time.h"
@@ -26,7 +30,7 @@
// Threshold constants to emit pressure events.
const int kNormalMemoryPressureModerateThresholdPercent = 60;
-const int kNormalMemoryPressureCriticalThresholdPercent = 90;
+const int kNormalMemoryPressureCriticalThresholdPercent = 95;
const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
@@ -40,13 +44,18 @@
NUM_MEMORY_PRESSURE_LEVELS
};
+// This is the file that will exist if low memory notification is available
+// on the device. Whenever it becomes readable, it signals a low memory
+// condition.
+const char kLowMemFile[] = "/dev/chromeos-low-mem";
+
// Converts a |MemoryPressureThreshold| value into a used memory percentage for
// the moderate pressure event.
int GetModerateMemoryThresholdInPercent(
- MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureObserverChromeOS::
+ MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) {
+ return thresholds == MemoryPressureMonitorChromeOS::
THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
- thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
+ thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE
? kAggressiveMemoryPressureModerateThresholdPercent
: kNormalMemoryPressureModerateThresholdPercent;
}
@@ -54,10 +63,10 @@
// Converts a |MemoryPressureThreshold| value into a used memory percentage for
// the critical pressure event.
int GetCriticalMemoryThresholdInPercent(
- MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureObserverChromeOS::
+ MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) {
+ return thresholds == MemoryPressureMonitorChromeOS::
THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
- thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
+ thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE
? kAggressiveMemoryPressureCriticalThresholdPercent
: kNormalMemoryPressureCriticalThresholdPercent;
}
@@ -74,9 +83,24 @@
: MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
}
+// This function will be called less then once a second. It will check if
+// the kernel has detected a low memory situation.
+bool IsLowMemoryCondition(int file_descriptor) {
+ fd_set fds;
+ struct timeval tv;
+
+ FD_ZERO(&fds);
+ FD_SET(file_descriptor, &fds);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0;
+}
+
} // namespace
-MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS(
+MemoryPressureMonitorChromeOS::MemoryPressureMonitorChromeOS(
MemoryPressureThresholds thresholds)
: current_memory_pressure_level_(
MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
@@ -85,35 +109,42 @@
GetModerateMemoryThresholdInPercent(thresholds)),
critical_pressure_threshold_percent_(
GetCriticalMemoryThresholdInPercent(thresholds)),
+ low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))),
weak_ptr_factory_(this) {
StartObserving();
+ LOG_IF(ERROR, !low_mem_file_.is_valid()) << "Cannot open kernel listener";
}
-MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() {
+MemoryPressureMonitorChromeOS::~MemoryPressureMonitorChromeOS() {
StopObserving();
}
-void MemoryPressureObserverChromeOS::ScheduleEarlyCheck() {
+void MemoryPressureMonitorChromeOS::ScheduleEarlyCheck() {
MessageLoop::current()->PostTask(
FROM_HERE,
- Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
+ Bind(&MemoryPressureMonitorChromeOS::CheckMemoryPressure,
weak_ptr_factory_.GetWeakPtr()));
}
-void MemoryPressureObserverChromeOS::StartObserving() {
+MemoryPressureListener::MemoryPressureLevel
+MemoryPressureMonitorChromeOS::GetCurrentPressureLevel() const {
+ return current_memory_pressure_level_;
+}
+
+void MemoryPressureMonitorChromeOS::StartObserving() {
timer_.Start(FROM_HERE,
TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
- Bind(&MemoryPressureObserverChromeOS::
+ Bind(&MemoryPressureMonitorChromeOS::
CheckMemoryPressureAndRecordStatistics,
weak_ptr_factory_.GetWeakPtr()));
}
-void MemoryPressureObserverChromeOS::StopObserving() {
+void MemoryPressureMonitorChromeOS::StopObserving() {
// If StartObserving failed, StopObserving will still get called.
timer_.Stop();
}
-void MemoryPressureObserverChromeOS::CheckMemoryPressureAndRecordStatistics() {
+void MemoryPressureMonitorChromeOS::CheckMemoryPressureAndRecordStatistics() {
CheckMemoryPressure();
// Record UMA histogram statistics for the current memory pressure level.
@@ -135,13 +166,35 @@
NUM_MEMORY_PRESSURE_LEVELS);
}
-void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
+void MemoryPressureMonitorChromeOS::CheckMemoryPressure() {
MemoryPressureListener::MemoryPressureLevel old_pressure =
current_memory_pressure_level_;
- current_memory_pressure_level_ =
- GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent(),
- moderate_pressure_threshold_percent_,
- critical_pressure_threshold_percent_);
+
+ // If we have the kernel low memory observer, we use it's flag instead of our
+ // own computation (for now). Note that in "simulation mode" it can be null.
+ // TODO(skuhne): We need to add code which makes sure that the kernel and this
+ // computation come to similar results and then remove this override again.
+ // TODO(skuhne): Add some testing framework here to see how close the kernel
+ // and the internal functions are.
+ if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) {
+ current_memory_pressure_level_ =
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
+ } else {
+ current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel(
+ GetUsedMemoryInPercent(),
+ moderate_pressure_threshold_percent_,
+ critical_pressure_threshold_percent_);
+
+ // When listening to the kernel, we ignore the reported memory pressure
+ // level from our own computation and reduce critical to moderate.
+ if (low_mem_file_.is_valid() &&
+ current_memory_pressure_level_ ==
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ current_memory_pressure_level_ =
+ MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
+ }
+ }
+
// In case there is no memory pressure we do not notify.
if (current_memory_pressure_level_ ==
MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
@@ -171,7 +224,7 @@
}
// Gets the used ChromeOS memory in percent.
-int MemoryPressureObserverChromeOS::GetUsedMemoryInPercent() {
+int MemoryPressureMonitorChromeOS::GetUsedMemoryInPercent() {
base::SystemMemoryInfoKB info;
if (!base::GetSystemMemoryInfo(&info)) {
VLOG(1) << "Cannot determine the free memory of the system.";
diff --git a/base/chromeos/memory_pressure_observer_chromeos.h b/base/chromeos/memory_pressure_monitor_chromeos.h
similarity index 78%
rename from base/chromeos/memory_pressure_observer_chromeos.h
rename to base/chromeos/memory_pressure_monitor_chromeos.h
index 9af07d4..45855eb 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.h
+++ b/base/chromeos/memory_pressure_monitor_chromeos.h
@@ -2,28 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
-#define BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
+#ifndef BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
+#define BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
#include "base/base_export.h"
+#include "base/files/scoped_file.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
namespace base {
-class TestMemoryPressureObserver;
+class TestMemoryPressureMonitor;
////////////////////////////////////////////////////////////////////////////////
-// MemoryPressureObserverChromeOS
+// MemoryPressureMonitorChromeOS
//
// A class to handle the observation of our free memory. It notifies the
// MemoryPressureListener of memory fill level changes, so that it can take
// action to reduce memory resources accordingly.
//
-class BASE_EXPORT MemoryPressureObserverChromeOS {
+class BASE_EXPORT MemoryPressureMonitorChromeOS : public MemoryPressureMonitor {
public:
using GetUsedMemoryInPercentCallback = int (*)();
@@ -47,8 +49,8 @@
THRESHOLD_AGGRESSIVE = 4
};
- explicit MemoryPressureObserverChromeOS(MemoryPressureThresholds thresholds);
- virtual ~MemoryPressureObserverChromeOS();
+ explicit MemoryPressureMonitorChromeOS(MemoryPressureThresholds thresholds);
+ ~MemoryPressureMonitorChromeOS() override;
// Redo the memory pressure calculation soon and call again if a critical
// memory pressure prevails. Note that this call will trigger an asynchronous
@@ -56,12 +58,11 @@
void ScheduleEarlyCheck();
// Get the current memory pressure level.
- base::MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() {
- return current_memory_pressure_level_;
- }
+ MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() const
+ override;
private:
- friend TestMemoryPressureObserver;
+ friend TestMemoryPressureMonitor;
// Starts observing the memory fill level.
// Calls to StartObserving should always be matched with calls to
// StopObserving.
@@ -89,7 +90,7 @@
// A periodic timer to check for resource pressure changes. This will get
// replaced by a kernel triggered event system (see crbug.com/381196).
- base::RepeatingTimer<MemoryPressureObserverChromeOS> timer_;
+ base::RepeatingTimer<MemoryPressureMonitorChromeOS> timer_;
// To slow down the amount of moderate pressure event calls, this counter
// gets used to count the number of events since the last event occured.
@@ -99,11 +100,14 @@
const int moderate_pressure_threshold_percent_;
const int critical_pressure_threshold_percent_;
- base::WeakPtrFactory<MemoryPressureObserverChromeOS> weak_ptr_factory_;
+ // File descriptor used to detect low memory condition.
+ ScopedFD low_mem_file_;
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureObserverChromeOS);
+ base::WeakPtrFactory<MemoryPressureMonitorChromeOS> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitorChromeOS);
};
} // namespace base
-#endif // BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
+#endif // BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
diff --git a/base/chromeos/memory_pressure_observer_chromeos_unittest.cc b/base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
similarity index 76%
rename from base/chromeos/memory_pressure_observer_chromeos_unittest.cc
rename to base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
index a227f93..72e00d3 100644
--- a/base/chromeos/memory_pressure_observer_chromeos_unittest.cc
+++ b/base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
-#include "base/chromeos/memory_pressure_observer_chromeos.h"
+#include "base/chromeos/memory_pressure_monitor_chromeos.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,17 +40,17 @@
} // namespace
-class TestMemoryPressureObserver : public MemoryPressureObserverChromeOS {
+class TestMemoryPressureMonitor : public MemoryPressureMonitorChromeOS {
public:
- TestMemoryPressureObserver() :
- MemoryPressureObserverChromeOS(
- MemoryPressureObserverChromeOS::THRESHOLD_DEFAULT),
+ TestMemoryPressureMonitor() :
+ MemoryPressureMonitorChromeOS(
+ MemoryPressureMonitorChromeOS::THRESHOLD_DEFAULT),
memory_in_percent_override_(0) {
// Disable any timers which are going on and set a special memory reporting
// function.
StopObserving();
}
- ~TestMemoryPressureObserver() override {}
+ ~TestMemoryPressureMonitor() override {}
void SetMemoryInPercentOverride(int percent) {
memory_in_percent_override_ = percent;
@@ -66,45 +66,45 @@
}
int memory_in_percent_override_;
- DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureObserver);
+ DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
};
// This test tests the various transition states from memory pressure, looking
// for the correct behavior on event reposting as well as state updates.
-TEST(MemoryPressureObserverChromeOSTest, CheckMemoryPressure) {
+TEST(MemoryPressureMonitorChromeOSTest, CheckMemoryPressure) {
base::MessageLoopForUI message_loop;
- scoped_ptr<TestMemoryPressureObserver> observer(
- new TestMemoryPressureObserver);
+ scoped_ptr<TestMemoryPressureMonitor> monitor(
+ new TestMemoryPressureMonitor);
scoped_ptr<MemoryPressureListener> listener(
new MemoryPressureListener(base::Bind(&OnMemoryPressure)));
// Checking the memory pressure while 0% are used should not produce any
// events.
- observer->SetMemoryInPercentOverride(0);
+ monitor->SetMemoryInPercentOverride(0);
ResetOnMemoryPressureCalled();
- observer->CheckMemoryPressureForTest();
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_FALSE(WasOnMemoryPressureCalled());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
// Setting the memory level to 80% should produce a moderate pressure level.
- observer->SetMemoryInPercentOverride(80);
- observer->CheckMemoryPressureForTest();
+ monitor->SetMemoryInPercentOverride(80);
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_TRUE(WasOnMemoryPressureCalled());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
on_memory_pressure_level);
// We need to check that the event gets reposted after a while.
int i = 0;
for (; i < 100; i++) {
- observer->CheckMemoryPressureForTest();
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
if (WasOnMemoryPressureCalled()) {
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
on_memory_pressure_level);
@@ -116,41 +116,41 @@
EXPECT_GE(99, i);
// Setting the memory usage to 99% should produce critical levels.
- observer->SetMemoryInPercentOverride(99);
- observer->CheckMemoryPressureForTest();
+ monitor->SetMemoryInPercentOverride(99);
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_TRUE(WasOnMemoryPressureCalled());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
on_memory_pressure_level);
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
// Calling it again should immediately produce a second call.
- observer->CheckMemoryPressureForTest();
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_TRUE(WasOnMemoryPressureCalled());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
on_memory_pressure_level);
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
// When lowering the pressure again we should not get an event, but the
// pressure should go back to moderate.
- observer->SetMemoryInPercentOverride(80);
- observer->CheckMemoryPressureForTest();
+ monitor->SetMemoryInPercentOverride(80);
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_FALSE(WasOnMemoryPressureCalled());
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
// We should need exactly the same amount of calls as before, before the next
// call comes in.
int j = 0;
for (; j < 100; j++) {
- observer->CheckMemoryPressureForTest();
+ monitor->CheckMemoryPressureForTest();
message_loop.RunUntilIdle();
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- observer->GetCurrentPressureLevel());
+ monitor->GetCurrentPressureLevel());
if (WasOnMemoryPressureCalled()) {
EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
on_memory_pressure_level);
diff --git a/base/command_line.cc b/base/command_line.cc
index d28a4b4..61ff5c1 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -263,7 +263,12 @@
}
bool CommandLine::HasSwitch(const std::string& switch_string) const {
- return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end();
+ DCHECK_EQ(StringToLowerASCII(switch_string), switch_string);
+ return switches_.find(switch_string) != switches_.end();
+}
+
+bool CommandLine::HasSwitch(const char string_constant[]) const {
+ return HasSwitch(std::string(string_constant));
}
std::string CommandLine::GetSwitchValueASCII(
diff --git a/base/command_line.h b/base/command_line.h
index 85d924a..439921e 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -142,8 +142,11 @@
void SetProgram(const FilePath& program);
// Returns true if this command line contains the given switch.
- // (Switch names are case-insensitive).
+ // Switch names should only be lowercase.
+ // The second override provides an optimized version to avoid inlining the
+ // codegen for the string allocation.
bool HasSwitch(const std::string& switch_string) const;
+ bool HasSwitch(const char switch_constant[]) const;
// Returns the value associated with the given switch. If the switch has no
// value or isn't present, this method returns the empty string.
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
index e395c85..db1a0b2 100644
--- a/base/command_line_unittest.cc
+++ b/base/command_line_unittest.cc
@@ -60,12 +60,13 @@
cl.GetProgram().value());
EXPECT_TRUE(cl.HasSwitch("foo"));
- EXPECT_TRUE(cl.HasSwitch("bAr"));
+#if defined(OS_WIN)
+ EXPECT_TRUE(cl.HasSwitch("bar"));
+#else
+ EXPECT_FALSE(cl.HasSwitch("bar"));
+#endif
EXPECT_TRUE(cl.HasSwitch("baz"));
EXPECT_TRUE(cl.HasSwitch("spaetzle"));
-#if defined(OS_WIN)
- EXPECT_TRUE(cl.HasSwitch("SPAETZLE"));
-#endif
EXPECT_TRUE(cl.HasSwitch("other-switches"));
EXPECT_TRUE(cl.HasSwitch("input-translation"));
@@ -128,7 +129,6 @@
EXPECT_TRUE(cl.HasSwitch("bar"));
EXPECT_TRUE(cl.HasSwitch("baz"));
EXPECT_TRUE(cl.HasSwitch("spaetzle"));
- EXPECT_TRUE(cl.HasSwitch("SPAETZLE"));
EXPECT_TRUE(cl.HasSwitch("other-switches"));
EXPECT_TRUE(cl.HasSwitch("input-translation"));
EXPECT_TRUE(cl.HasSwitch("quotes"));
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 034cf06..63297dc 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -128,13 +128,11 @@
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#endif
-// Return the byte alignment of the given type (available at compile time). Use
-// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
-// http://goo.gl/isH0C
+// Return the byte alignment of the given type (available at compile time).
// Use like:
// ALIGNOF(int32) // this would be 4
#if defined(COMPILER_MSVC)
-#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
+#define ALIGNOF(type) __alignof(type)
#elif defined(COMPILER_GCC)
#define ALIGNOF(type) __alignof__(type)
#endif
diff --git a/base/file_version_info_win.h b/base/file_version_info_win.h
index 0e0f271..92d0844 100644
--- a/base/file_version_info_win.h
+++ b/base/file_version_info_win.h
@@ -18,26 +18,26 @@
class FileVersionInfoWin : public FileVersionInfo {
public:
BASE_EXPORT FileVersionInfoWin(void* data, WORD language, WORD code_page);
- BASE_EXPORT ~FileVersionInfoWin();
+ BASE_EXPORT ~FileVersionInfoWin() override;
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
- virtual base::string16 company_name() override;
- virtual base::string16 company_short_name() override;
- virtual base::string16 product_name() override;
- virtual base::string16 product_short_name() override;
- virtual base::string16 internal_name() override;
- virtual base::string16 product_version() override;
- virtual base::string16 private_build() override;
- virtual base::string16 special_build() override;
- virtual base::string16 comments() override;
- virtual base::string16 original_filename() override;
- virtual base::string16 file_description() override;
- virtual base::string16 file_version() override;
- virtual base::string16 legal_copyright() override;
- virtual base::string16 legal_trademarks() override;
- virtual base::string16 last_change() override;
- virtual bool is_official_build() override;
+ base::string16 company_name() override;
+ base::string16 company_short_name() override;
+ base::string16 product_name() override;
+ base::string16 product_short_name() override;
+ base::string16 internal_name() override;
+ base::string16 product_version() override;
+ base::string16 private_build() override;
+ base::string16 special_build() override;
+ base::string16 comments() override;
+ base::string16 original_filename() override;
+ base::string16 file_description() override;
+ base::string16 file_version() override;
+ base::string16 legal_copyright() override;
+ base::string16 legal_trademarks() override;
+ base::string16 last_change() override;
+ bool is_official_build() override;
// Lets you access other properties not covered above.
BASE_EXPORT bool GetValue(const wchar_t* name, std::wstring* value);
diff --git a/base/files/file.cc b/base/files/file.cc
index a997074..8030bf1 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -4,10 +4,8 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
-
-#if defined(OS_POSIX)
-#include "base/files/file_posix_hooks_internal.h"
-#endif
+#include "base/metrics/histogram.h"
+#include "base/timer/elapsed_timer.h"
namespace base {
@@ -42,8 +40,6 @@
async_(false) {
#if defined(OS_POSIX)
DCHECK_GE(platform_file, -1);
- if (IsValid())
- ProtectFileDescriptor(platform_file);
#endif
}
@@ -58,10 +54,6 @@
error_details_(other.object->error_details()),
created_(other.object->created()),
async_(other.object->async_) {
-#if defined(OS_POSIX)
- if (IsValid())
- ProtectFileDescriptor(GetPlatformFile());
-#endif
}
File::~File() {
@@ -86,7 +78,7 @@
error_details_ = FILE_ERROR_ACCESS_DENIED;
return;
}
- InitializeUnsafe(name, flags);
+ DoInitialize(name, flags);
}
#endif
@@ -134,4 +126,11 @@
return "";
}
+bool File::Flush() {
+ ElapsedTimer timer;
+ bool return_value = DoFlush();
+ UMA_HISTOGRAM_TIMES("PlatformFile.FlushTime", timer.Elapsed());
+ return return_value;
+}
+
} // namespace base
diff --git a/base/files/file.h b/base/files/file.h
index 13c8a96..89077b4 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -150,13 +150,13 @@
bool is_symbolic_link;
// The last modified time of a file.
- base::Time last_modified;
+ Time last_modified;
// The last accessed time of a file.
- base::Time last_accessed;
+ Time last_accessed;
// The creation time of a file.
- base::Time creation_time;
+ Time creation_time;
};
File();
@@ -182,10 +182,6 @@
// Creates or opens the given file.
void Initialize(const FilePath& name, uint32 flags);
- // Creates or opens the given file, allowing paths with traversal ('..')
- // components. Use only with extreme care.
- void InitializeUnsafe(const FilePath& name, uint32 flags);
-
bool IsValid() const;
// Returns true if a new file was created (or an old one truncated to zero
@@ -354,6 +350,14 @@
};
#endif
+ // Creates or opens the given file. Only called if |name| has no traversal
+ // ('..') components.
+ void DoInitialize(const FilePath& name, uint32 flags);
+
+ // TODO(tnagel): Reintegrate into Flush() once histogram isn't needed anymore,
+ // cf. issue 473337.
+ bool DoFlush();
+
void SetPlatformFile(PlatformFile file);
#if defined(OS_WIN)
diff --git a/base/files/file_path.h b/base/files/file_path.h
index 93f9ec9..5225b12 100644
--- a/base/files/file_path.h
+++ b/base/files/file_path.h
@@ -443,11 +443,9 @@
#if defined(OS_POSIX)
#define FILE_PATH_LITERAL(x) x
#define PRFilePath "s"
-#define PRFilePathLiteral "%s"
#elif defined(OS_WIN)
#define FILE_PATH_LITERAL(x) L ## x
#define PRFilePath "ls"
-#define PRFilePathLiteral L"%ls"
#endif // OS_WIN
// Provide a hash function so that hash_sets and maps can contain FilePath
diff --git a/base/files/file_path_watcher.cc b/base/files/file_path_watcher.cc
index b173541..59ae705 100644
--- a/base/files/file_path_watcher.cc
+++ b/base/files/file_path_watcher.cc
@@ -32,7 +32,7 @@
// FSEvents isn't available on iOS and is broken on OSX 10.6 and earlier.
// See http://crbug.com/54822#c31
return mac::IsOSLionOrLater();
-#elif defined(OS_WIN) || defined(OS_LINUX)
+#elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
return true;
#else
return false;
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
index f240e33..ef4e6ee 100644
--- a/base/files/file_path_watcher_fsevents.cc
+++ b/base/files/file_path_watcher_fsevents.cc
@@ -75,11 +75,51 @@
return result;
}
-// The callback passed to FSEventStreamCreate().
-void FSEventsCallback(ConstFSEventStreamRef stream,
- void* event_watcher, size_t num_events,
- void* event_paths, const FSEventStreamEventFlags flags[],
- const FSEventStreamEventId event_ids[]) {
+} // namespace
+
+FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
+}
+
+bool FilePathWatcherFSEvents::Watch(const FilePath& path,
+ bool recursive,
+ const FilePathWatcher::Callback& callback) {
+ DCHECK(MessageLoopForIO::current());
+ DCHECK(!callback.is_null());
+ DCHECK(callback_.is_null());
+
+ // This class could support non-recursive watches, but that is currently
+ // left to FilePathWatcherKQueue.
+ if (!recursive)
+ return false;
+
+ set_message_loop(MessageLoopProxy::current());
+ callback_ = callback;
+
+ FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
+ g_task_runner.Get().PostTask(
+ FROM_HERE, Bind(&FilePathWatcherFSEvents::StartEventStream, this,
+ start_event, path));
+ return true;
+}
+
+void FilePathWatcherFSEvents::Cancel() {
+ set_cancelled();
+ callback_.Reset();
+
+ // Switch to the dispatch queue thread to tear down the event stream.
+ g_task_runner.Get().PostTask(
+ FROM_HERE,
+ Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
+}
+
+// static
+void FilePathWatcherFSEvents::FSEventsCallback(
+ ConstFSEventStreamRef stream,
+ void* event_watcher,
+ size_t num_events,
+ void* event_paths,
+ const FSEventStreamEventFlags flags[],
+ const FSEventStreamEventId event_ids[]) {
FilePathWatcherFSEvents* watcher =
reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher);
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
@@ -111,83 +151,51 @@
watcher->OnFilePathsChanged(paths);
}
-} // namespace
-
-FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
+FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {
+ // This method may be called on either the libdispatch or message_loop()
+ // thread. Checking callback_ on the libdispatch thread here is safe because
+ // it is executing in a task posted by Cancel() which first reset callback_.
+ // PostTask forms a sufficient memory barrier to ensure that the value is
+ // consistent on the target thread.
+ DCHECK(callback_.is_null())
+ << "Cancel() must be called before FilePathWatcher is destroyed.";
}
void FilePathWatcherFSEvents::OnFilePathsChanged(
const std::vector<FilePath>& paths) {
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::OnFilePathsChanged, this, paths));
+ DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
+ DCHECK(!resolved_target_.empty());
+ message_loop()->PostTask(
+ FROM_HERE, Bind(&FilePathWatcherFSEvents::DispatchEvents, this, paths,
+ target_, resolved_target_));
+}
+
+void FilePathWatcherFSEvents::DispatchEvents(const std::vector<FilePath>& paths,
+ const FilePath& target,
+ const FilePath& resolved_target) {
+ DCHECK(message_loop()->RunsTasksOnCurrentThread());
+
+ // Don't issue callbacks after Cancel() has been called.
+ if (is_cancelled() || callback_.is_null()) {
return;
}
- DCHECK(message_loop()->BelongsToCurrentThread());
- if (resolved_target_.empty())
- return;
-
- for (size_t i = 0; i < paths.size(); i++) {
- if (resolved_target_.IsParent(paths[i]) || resolved_target_ == paths[i]) {
- callback_.Run(target_, false);
+ for (const FilePath& path : paths) {
+ if (resolved_target.IsParent(path) || resolved_target == path) {
+ callback_.Run(target, false);
return;
}
}
}
-bool FilePathWatcherFSEvents::Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) {
- DCHECK(resolved_target_.empty());
- DCHECK(MessageLoopForIO::current());
- DCHECK(!callback.is_null());
-
- // This class could support non-recursive watches, but that is currently
- // left to FilePathWatcherKQueue.
- if (!recursive)
- return false;
-
- set_message_loop(MessageLoopProxy::current());
- callback_ = callback;
- target_ = path;
-
- FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
- g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::StartEventStream, this, start_event));
- return true;
-}
-
-void FilePathWatcherFSEvents::Cancel() {
- if (callback_.is_null()) {
- // Watch was never called, so exit.
- set_cancelled();
- return;
- }
-
- // Switch to the dispatch queue thread if necessary, so we can tear down
- // the event stream.
- if (!g_task_runner.Get().RunsTasksOnCurrentThread()) {
- g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
- } else {
- CancelOnMessageLoopThread();
- }
-}
-
void FilePathWatcherFSEvents::CancelOnMessageLoopThread() {
// For all other implementations, the "message loop thread" is the IO thread,
// as returned by message_loop(). This implementation, however, needs to
- // cancel pending work on the Dipatch Queue thread.
+ // cancel pending work on the Dispatch Queue thread.
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
- set_cancelled();
if (fsevent_stream_) {
DestroyEventStream();
- callback_.Reset();
target_.clear();
resolved_target_.clear();
}
@@ -199,7 +207,7 @@
// It can happen that the watcher gets canceled while tasks that call this
// function are still in flight, so abort if this situation is detected.
- if (is_cancelled() || resolved_target_.empty())
+ if (resolved_target_.empty())
return;
if (fsevent_stream_)
@@ -230,8 +238,10 @@
FSEventStreamSetDispatchQueue(fsevent_stream_,
g_task_runner.Get().GetDispatchQueue());
- if (!FSEventStreamStart(fsevent_stream_))
- message_loop()->PostTask(FROM_HERE, Bind(callback_, target_, true));
+ if (!FSEventStreamStart(fsevent_stream_)) {
+ message_loop()->PostTask(
+ FROM_HERE, Bind(&FilePathWatcherFSEvents::ReportError, this, target_));
+ }
}
bool FilePathWatcherFSEvents::ResolveTargetPath() {
@@ -239,11 +249,20 @@
FilePath resolved = ResolvePath(target_).StripTrailingSeparators();
bool changed = resolved != resolved_target_;
resolved_target_ = resolved;
- if (resolved_target_.empty())
- message_loop()->PostTask(FROM_HERE, Bind(callback_, target_, true));
+ if (resolved_target_.empty()) {
+ message_loop()->PostTask(
+ FROM_HERE, Bind(&FilePathWatcherFSEvents::ReportError, this, target_));
+ }
return changed;
}
+void FilePathWatcherFSEvents::ReportError(const FilePath& target) {
+ DCHECK(message_loop()->RunsTasksOnCurrentThread());
+ if (!callback_.is_null()) {
+ callback_.Run(target, true);
+ }
+}
+
void FilePathWatcherFSEvents::DestroyEventStream() {
FSEventStreamStop(fsevent_stream_);
FSEventStreamInvalidate(fsevent_stream_);
@@ -251,13 +270,14 @@
fsevent_stream_ = NULL;
}
-void FilePathWatcherFSEvents::StartEventStream(
- FSEventStreamEventId start_event) {
+void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event,
+ const FilePath& path) {
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
+ DCHECK(resolved_target_.empty());
+
+ target_ = path;
ResolveTargetPath();
UpdateEventStream(start_event);
}
-FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {}
-
} // namespace base
diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h
index 800c5b4..300aa76 100644
--- a/base/files/file_path_watcher_fsevents.h
+++ b/base/files/file_path_watcher_fsevents.h
@@ -24,9 +24,35 @@
public:
FilePathWatcherFSEvents();
- // Called from the FSEvents callback whenever there is a change to the paths.
+ // FilePathWatcher::PlatformDelegate overrides.
+ bool Watch(const FilePath& path,
+ bool recursive,
+ const FilePathWatcher::Callback& callback) override;
+ void Cancel() override;
+
+ private:
+ static void FSEventsCallback(ConstFSEventStreamRef stream,
+ void* event_watcher,
+ size_t num_events,
+ void* event_paths,
+ const FSEventStreamEventFlags flags[],
+ const FSEventStreamEventId event_ids[]);
+
+ ~FilePathWatcherFSEvents() override;
+
+ // Called from FSEventsCallback whenever there is a change to the paths.
void OnFilePathsChanged(const std::vector<FilePath>& paths);
+ // Called on the message_loop() thread to dispatch path events. Can't access
+ // target_ and resolved_target_ directly as those are modified on the
+ // libdispatch thread.
+ void DispatchEvents(const std::vector<FilePath>& paths,
+ const FilePath& target,
+ const FilePath& resolved_target);
+
+ // Cleans up and stops the event stream.
+ void CancelOnMessageLoopThread() override;
+
// (Re-)Initialize the event stream to start reporting events from
// |start_event|.
void UpdateEventStream(FSEventStreamEventId start_event);
@@ -35,34 +61,29 @@
// last time it was done.
bool ResolveTargetPath();
- // FilePathWatcher::PlatformDelegate overrides.
- bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override;
- void Cancel() override;
-
- private:
- ~FilePathWatcherFSEvents() override;
+ // Report an error watching the given target.
+ void ReportError(const FilePath& target);
// Destroy the event stream.
void DestroyEventStream();
// Start watching the FSEventStream.
- void StartEventStream(FSEventStreamEventId start_event);
-
- // Cleans up and stops the event stream.
- void CancelOnMessageLoopThread() override;
+ void StartEventStream(FSEventStreamEventId start_event, const FilePath& path);
// Callback to notify upon changes.
+ // (Only accessed from the message_loop() thread.)
FilePathWatcher::Callback callback_;
// Target path to watch (passed to callback).
+ // (Only accessed from the libdispatch thread.)
FilePath target_;
// Target path with all symbolic links resolved.
+ // (Only accessed from the libdispatch thread.)
FilePath resolved_target_;
// Backend stream we receive event callbacks from (strong reference).
+ // (Only accessed from the libdispatch thread.)
FSEventStreamRef fsevent_stream_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
diff --git a/base/files/file_path_watcher_stub.cc b/base/files/file_path_watcher_stub.cc
index d7ad206..8138692 100644
--- a/base/files/file_path_watcher_stub.cc
+++ b/base/files/file_path_watcher_stub.cc
@@ -13,18 +13,18 @@
class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
public:
- virtual bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override {
+ bool Watch(const FilePath& path,
+ bool recursive,
+ const FilePathWatcher::Callback& callback) override {
return false;
}
- virtual void Cancel() override {}
+ void Cancel() override {}
- virtual void CancelOnMessageLoopThread() override {}
+ void CancelOnMessageLoopThread() override {}
protected:
- virtual ~FilePathWatcherImpl() {}
+ ~FilePathWatcherImpl() override {}
};
} // namespace
diff --git a/base/files/file_path_watcher_browsertest.cc b/base/files/file_path_watcher_unittest.cc
similarity index 93%
rename from base/files/file_path_watcher_browsertest.cc
rename to base/files/file_path_watcher_unittest.cc
index bc7e630..0e1c467 100644
--- a/base/files/file_path_watcher_browsertest.cc
+++ b/base/files/file_path_watcher_unittest.cc
@@ -31,6 +31,10 @@
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_ANDROID)
+#include "base/android/path_utils.h"
+#endif // defined(OS_ANDROID)
+
namespace base {
namespace {
@@ -150,7 +154,17 @@
// Create a separate file thread in order to test proper thread usage.
base::Thread::Options options(MessageLoop::TYPE_IO, 0);
ASSERT_TRUE(file_thread_.StartWithOptions(options));
+#if defined(OS_ANDROID)
+ // Watching files is only permitted when all parent directories are
+ // accessible, which is not the case for the default temp directory
+ // on Android which is under /data/data. Use /sdcard instead.
+ // TODO(pauljensen): Remove this when crbug.com/475568 is fixed.
+ FilePath parent_dir;
+ ASSERT_TRUE(android::GetExternalStorageDirectory(&parent_dir));
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDirUnderPath(parent_dir));
+#else // defined(OS_ANDROID)
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+#endif // defined(OS_ANDROID)
collector_ = new NotificationCollector();
}
@@ -526,9 +540,16 @@
ASSERT_TRUE(WriteFile(child_dir_file1, "content"));
ASSERT_TRUE(WaitForEvents());
+// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4". Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#if !defined(OS_ANDROID)
// Modify "$dir/subdir/subdir_child_dir/child_dir_file1" attributes.
ASSERT_TRUE(base::MakeFileUnreadable(child_dir_file1));
ASSERT_TRUE(WaitForEvents());
+#endif
// Delete "$dir/subdir/subdir_file1".
ASSERT_TRUE(base::DeleteFile(subdir_file1, false));
@@ -541,6 +562,14 @@
}
#if defined(OS_POSIX)
+#if defined(OS_ANDROID)
+// Apps cannot create symlinks on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4". Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#define RecursiveWithSymLink DISABLED_RecursiveWithSymLink
+#endif // defined(OS_ANDROID)
TEST_F(FilePathWatcherTest, RecursiveWithSymLink) {
if (!FilePathWatcher::RecursiveWatchAvailable())
return;
@@ -610,6 +639,14 @@
}
// Verify that changing attributes on a file is caught
+#if defined(OS_ANDROID)
+// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4". Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#define FileAttributesChanged DISABLED_FileAttributesChanged
+#endif // defined(OS_ANDROID
TEST_F(FilePathWatcherTest, FileAttributesChanged) {
ASSERT_TRUE(WriteFile(test_file(), "content"));
FilePathWatcher watcher;
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index f6d0029..d7ce524 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -27,21 +27,21 @@
recursive_watch_(false) {}
// FilePathWatcher::PlatformDelegate overrides.
- virtual bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override;
- virtual void Cancel() override;
+ bool Watch(const FilePath& path,
+ bool recursive,
+ const FilePathWatcher::Callback& callback) override;
+ void Cancel() override;
// Deletion of the FilePathWatcher will call Cancel() to dispose of this
// object in the right thread. This also observes destruction of the required
// cleanup thread, in case it quits before Cancel() is called.
- virtual void WillDestroyCurrentMessageLoop() override;
+ void WillDestroyCurrentMessageLoop() override;
// Callback from MessageLoopForIO.
- virtual void OnObjectSignaled(HANDLE object) override;
+ void OnObjectSignaled(HANDLE object) override;
private:
- virtual ~FilePathWatcherImpl() {}
+ ~FilePathWatcherImpl() override {}
// Setup a watch handle for directory |dir|. Set |recursive| to true to watch
// the directory sub trees. Returns true if no fatal error occurs. |handle|
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 517390f..4c79057 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -10,7 +10,6 @@
#include <unistd.h>
#include "base/files/file_path.h"
-#include "base/files/file_posix_hooks_internal.h"
#include "base/logging.h"
#include "base/metrics/sparse_histogram.h"
#include "base/posix/eintr_wrapper.h"
@@ -32,12 +31,12 @@
#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
static int CallFstat(int fd, stat_wrapper_t *sb) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
return fstat(fd, sb);
}
#else
static int CallFstat(int fd, stat_wrapper_t *sb) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
return fstat64(fd, sb);
}
#endif
@@ -53,10 +52,6 @@
return HANDLE_EINTR(ftruncate(file, length));
}
-static int CallFsync(PlatformFile file) {
- return HANDLE_EINTR(fsync(file));
-}
-
static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
#ifdef __USE_XOPEN2K8
// futimens should be available, but futimes might not be
@@ -98,11 +93,6 @@
return 0;
}
-static int CallFsync(PlatformFile file) {
- NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
- return 0;
-}
-
static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
NOTIMPLEMENTED(); // NaCl doesn't implement futimes.
return 0;
@@ -167,104 +157,6 @@
Time::kNanosecondsPerMicrosecond);
}
-// Default implementations of Protect/Unprotect hooks defined as weak symbols
-// where possible.
-void ProtectFileDescriptor(int fd) {
-}
-
-void UnprotectFileDescriptor(int fd) {
-}
-
-// NaCl doesn't implement system calls to open files directly.
-#if !defined(OS_NACL)
-// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
-void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(!IsValid());
-
- int open_flags = 0;
- if (flags & FLAG_CREATE)
- open_flags = O_CREAT | O_EXCL;
-
- created_ = false;
-
- if (flags & FLAG_CREATE_ALWAYS) {
- DCHECK(!open_flags);
- DCHECK(flags & FLAG_WRITE);
- open_flags = O_CREAT | O_TRUNC;
- }
-
- if (flags & FLAG_OPEN_TRUNCATED) {
- DCHECK(!open_flags);
- DCHECK(flags & FLAG_WRITE);
- open_flags = O_TRUNC;
- }
-
- if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
- NOTREACHED();
- errno = EOPNOTSUPP;
- error_details_ = FILE_ERROR_FAILED;
- return;
- }
-
- if (flags & FLAG_WRITE && flags & FLAG_READ) {
- open_flags |= O_RDWR;
- } else if (flags & FLAG_WRITE) {
- open_flags |= O_WRONLY;
- } else if (!(flags & FLAG_READ) &&
- !(flags & FLAG_WRITE_ATTRIBUTES) &&
- !(flags & FLAG_APPEND) &&
- !(flags & FLAG_OPEN_ALWAYS)) {
- NOTREACHED();
- }
-
- if (flags & FLAG_TERMINAL_DEVICE)
- open_flags |= O_NOCTTY | O_NDELAY;
-
- if (flags & FLAG_APPEND && flags & FLAG_READ)
- open_flags |= O_APPEND | O_RDWR;
- else if (flags & FLAG_APPEND)
- open_flags |= O_APPEND | O_WRONLY;
-
- COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
-
- int mode = S_IRUSR | S_IWUSR;
-#if defined(OS_CHROMEOS)
- mode |= S_IRGRP | S_IROTH;
-#endif
-
- int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
-
- if (flags & FLAG_OPEN_ALWAYS) {
- if (descriptor < 0) {
- open_flags |= O_CREAT;
- if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
- open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
-
- descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
- if (descriptor >= 0)
- created_ = true;
- }
- }
-
- if (descriptor < 0) {
- error_details_ = File::OSErrorToFileError(errno);
- return;
- }
-
- if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
- created_ = true;
-
- if (flags & FLAG_DELETE_ON_CLOSE)
- unlink(name.value().c_str());
-
- async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
- error_details_ = FILE_OK;
- file_.reset(descriptor);
- ProtectFileDescriptor(descriptor);
-}
-#endif // !defined(OS_NACL)
-
bool File::IsValid() const {
return file_.is_valid();
}
@@ -274,8 +166,6 @@
}
PlatformFile File::TakePlatformFile() {
- if (IsValid())
- UnprotectFileDescriptor(GetPlatformFile());
return file_.release();
}
@@ -283,13 +173,12 @@
if (!IsValid())
return;
- base::ThreadRestrictions::AssertIOAllowed();
- UnprotectFileDescriptor(GetPlatformFile());
+ ThreadRestrictions::AssertIOAllowed();
file_.reset();
}
int64 File::Seek(Whence whence, int64 offset) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
#if defined(OS_ANDROID)
@@ -304,7 +193,7 @@
}
int File::Read(int64 offset, char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
if (size < 0)
return -1;
@@ -324,7 +213,7 @@
}
int File::ReadAtCurrentPos(char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
if (size < 0)
return -1;
@@ -343,14 +232,14 @@
}
int File::ReadNoBestEffort(int64 offset, char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
return HANDLE_EINTR(pread(file_.get(), data, size, offset));
}
int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
if (size < 0)
return -1;
@@ -359,7 +248,7 @@
}
int File::Write(int64 offset, const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
if (IsOpenAppend(file_.get()))
return WriteAtCurrentPos(data, size);
@@ -383,7 +272,7 @@
}
int File::WriteAtCurrentPos(const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
if (size < 0)
return -1;
@@ -403,7 +292,7 @@
}
int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
if (size < 0)
return -1;
@@ -422,19 +311,13 @@
}
bool File::SetLength(int64 length) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
return !CallFtruncate(file_.get(), length);
}
-bool File::Flush() {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- return !CallFsync(file_.get());
-}
-
bool File::SetTimes(Time last_access_time, Time last_modified_time) {
- base::ThreadRestrictions::AssertIOAllowed();
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
timeval times[2];
@@ -556,11 +439,111 @@
ComputeMemoryChecksum(&file_memory_checksum_);
}
+// NaCl doesn't implement system calls to open files directly.
+#if !defined(OS_NACL)
+// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
+void File::DoInitialize(const FilePath& name, uint32 flags) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(!IsValid());
+
+ int open_flags = 0;
+ if (flags & FLAG_CREATE)
+ open_flags = O_CREAT | O_EXCL;
+
+ created_ = false;
+
+ if (flags & FLAG_CREATE_ALWAYS) {
+ DCHECK(!open_flags);
+ DCHECK(flags & FLAG_WRITE);
+ open_flags = O_CREAT | O_TRUNC;
+ }
+
+ if (flags & FLAG_OPEN_TRUNCATED) {
+ DCHECK(!open_flags);
+ DCHECK(flags & FLAG_WRITE);
+ open_flags = O_TRUNC;
+ }
+
+ if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
+ NOTREACHED();
+ errno = EOPNOTSUPP;
+ error_details_ = FILE_ERROR_FAILED;
+ return;
+ }
+
+ if (flags & FLAG_WRITE && flags & FLAG_READ) {
+ open_flags |= O_RDWR;
+ } else if (flags & FLAG_WRITE) {
+ open_flags |= O_WRONLY;
+ } else if (!(flags & FLAG_READ) &&
+ !(flags & FLAG_WRITE_ATTRIBUTES) &&
+ !(flags & FLAG_APPEND) &&
+ !(flags & FLAG_OPEN_ALWAYS)) {
+ NOTREACHED();
+ }
+
+ if (flags & FLAG_TERMINAL_DEVICE)
+ open_flags |= O_NOCTTY | O_NDELAY;
+
+ if (flags & FLAG_APPEND && flags & FLAG_READ)
+ open_flags |= O_APPEND | O_RDWR;
+ else if (flags & FLAG_APPEND)
+ open_flags |= O_APPEND | O_WRONLY;
+
+ COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
+
+ int mode = S_IRUSR | S_IWUSR;
+#if defined(OS_CHROMEOS)
+ mode |= S_IRGRP | S_IROTH;
+#endif
+
+ int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+
+ if (flags & FLAG_OPEN_ALWAYS) {
+ if (descriptor < 0) {
+ open_flags |= O_CREAT;
+ if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
+ open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
+
+ descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+ if (descriptor >= 0)
+ created_ = true;
+ }
+ }
+
+ if (descriptor < 0) {
+ error_details_ = File::OSErrorToFileError(errno);
+ return;
+ }
+
+ if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
+ created_ = true;
+
+ if (flags & FLAG_DELETE_ON_CLOSE)
+ unlink(name.value().c_str());
+
+ async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
+ error_details_ = FILE_OK;
+ file_.reset(descriptor);
+}
+#endif // !defined(OS_NACL)
+
+bool File::DoFlush() {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+#if defined(OS_NACL)
+ NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
+ return true;
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+ return !HANDLE_EINTR(fdatasync(file_.get()));
+#else
+ return !HANDLE_EINTR(fsync(file_.get()));
+#endif
+}
+
void File::SetPlatformFile(PlatformFile file) {
- CHECK(!file_.is_valid());
+ DCHECK(!file_.is_valid());
file_.reset(file);
- if (file_.is_valid())
- ProtectFileDescriptor(GetPlatformFile());
}
} // namespace base
diff --git a/base/files/file_posix_hooks_internal.h b/base/files/file_posix_hooks_internal.h
deleted file mode 100644
index 1137b48..0000000
--- a/base/files/file_posix_hooks_internal.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
-#define BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
-
-#include "base/base_export.h"
-
-namespace base {
-
-// Define empty hooks for blacklisting file descriptors used in base::File.
-// These functions should be declared 'weak', i.e. the functions declared in
-// a default way would have precedence over the weak ones at link time. This
-// works for both static and dynamic linking.
-// TODO(pasko): Remove these hooks when crbug.com/424562 is fixed.
-//
-// With compilers other than GCC/Clang define strong no-op symbols for
-// simplicity.
-#if defined(COMPILER_GCC)
-#define ATTRIBUTE_WEAK __attribute__ ((weak))
-#else
-#define ATTRIBUTE_WEAK
-#endif
-BASE_EXPORT void ProtectFileDescriptor(int fd) ATTRIBUTE_WEAK;
-BASE_EXPORT void UnprotectFileDescriptor(int fd) ATTRIBUTE_WEAK;
-#undef ATTRIBUTE_WEAK
-
-} // namespace base
-
-#endif // BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index dad8edd..b4a64ba 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -57,7 +57,6 @@
namespace base {
-#if !defined(OS_NACL_NONSFI)
namespace {
#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
@@ -80,6 +79,7 @@
}
#endif // !(defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL))
+#if !defined(OS_NACL_NONSFI)
// Helper for NormalizeFilePath(), defined below.
bool RealPath(const FilePath& path, FilePath* real_path) {
ThreadRestrictions::AssertIOAllowed(); // For realpath().
@@ -182,9 +182,11 @@
return result;
}
#endif // defined(OS_LINUX)
+#endif // !defined(OS_NACL_NONSFI)
} // namespace
+#if !defined(OS_NACL_NONSFI)
FilePath MakeAbsoluteFilePath(const FilePath& input) {
ThreadRestrictions::AssertIOAllowed();
char full_path[PATH_MAX];
@@ -363,6 +365,7 @@
ThreadRestrictions::AssertIOAllowed();
return access(path.value().c_str(), W_OK) == 0;
}
+#endif // !defined(OS_NACL_NONSFI)
bool DirectoryExists(const FilePath& path) {
ThreadRestrictions::AssertIOAllowed();
@@ -371,7 +374,6 @@
return S_ISDIR(file_info.st_mode);
return false;
}
-#endif // !defined(OS_NACL_NONSFI)
bool ReadFromFD(int fd, char* buffer, size_t bytes) {
size_t total_read = 0;
diff --git a/base/files/file_win.cc b/base/files/file_win.cc
index 9f3033c..200ea29 100644
--- a/base/files/file_win.cc
+++ b/base/files/file_win.cc
@@ -18,8 +18,268 @@
File::FROM_CURRENT == FILE_CURRENT &&
File::FROM_END == FILE_END, whence_matches_system);
-void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
- base::ThreadRestrictions::AssertIOAllowed();
+bool File::IsValid() const {
+ return file_.IsValid();
+}
+
+PlatformFile File::GetPlatformFile() const {
+ return file_.Get();
+}
+
+PlatformFile File::TakePlatformFile() {
+ return file_.Take();
+}
+
+void File::Close() {
+ if (file_.IsValid()) {
+ ThreadRestrictions::AssertIOAllowed();
+ file_.Close();
+ }
+}
+
+int64 File::Seek(Whence whence, int64 offset) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+
+ LARGE_INTEGER distance, res;
+ distance.QuadPart = offset;
+ DWORD move_method = static_cast<DWORD>(whence);
+ if (!SetFilePointerEx(file_.Get(), distance, &res, move_method))
+ return -1;
+ return res.QuadPart;
+}
+
+int File::Read(int64 offset, char* data, int size) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+ DCHECK(!async_);
+ if (size < 0)
+ return -1;
+
+ LARGE_INTEGER offset_li;
+ offset_li.QuadPart = offset;
+
+ OVERLAPPED overlapped = {0};
+ overlapped.Offset = offset_li.LowPart;
+ overlapped.OffsetHigh = offset_li.HighPart;
+
+ DWORD bytes_read;
+ if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped))
+ return bytes_read;
+ if (ERROR_HANDLE_EOF == GetLastError())
+ return 0;
+
+ return -1;
+}
+
+int File::ReadAtCurrentPos(char* data, int size) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+ DCHECK(!async_);
+ if (size < 0)
+ return -1;
+
+ DWORD bytes_read;
+ if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL))
+ return bytes_read;
+ if (ERROR_HANDLE_EOF == GetLastError())
+ return 0;
+
+ return -1;
+}
+
+int File::ReadNoBestEffort(int64 offset, char* data, int size) {
+ return Read(offset, data, size);
+}
+
+int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
+ return ReadAtCurrentPos(data, size);
+}
+
+int File::Write(int64 offset, const char* data, int size) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+ DCHECK(!async_);
+
+ LARGE_INTEGER offset_li;
+ offset_li.QuadPart = offset;
+
+ OVERLAPPED overlapped = {0};
+ overlapped.Offset = offset_li.LowPart;
+ overlapped.OffsetHigh = offset_li.HighPart;
+
+ DWORD bytes_written;
+ if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped))
+ return bytes_written;
+
+ return -1;
+}
+
+int File::WriteAtCurrentPos(const char* data, int size) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+ DCHECK(!async_);
+ if (size < 0)
+ return -1;
+
+ DWORD bytes_written;
+ if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL))
+ return bytes_written;
+
+ return -1;
+}
+
+int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
+ return WriteAtCurrentPos(data, size);
+}
+
+int64 File::GetLength() {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+ LARGE_INTEGER size;
+ if (!::GetFileSizeEx(file_.Get(), &size))
+ return -1;
+
+ return static_cast<int64>(size.QuadPart);
+}
+
+bool File::SetLength(int64 length) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+
+ // Get the current file pointer.
+ LARGE_INTEGER file_pointer;
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+ if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT))
+ return false;
+
+ LARGE_INTEGER length_li;
+ length_li.QuadPart = length;
+ // If length > file size, SetFilePointerEx() should extend the file
+ // with zeroes on all Windows standard file systems (NTFS, FATxx).
+ if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN))
+ return false;
+
+ // Set the new file length and move the file pointer to its old position.
+ // This is consistent with ftruncate()'s behavior, even when the file
+ // pointer points to a location beyond the end of the file.
+ // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not
+ // promised by the interface (nor was promised by PlatformFile). See if this
+ // implementation detail can be removed.
+ return ((::SetEndOfFile(file_.Get()) != FALSE) &&
+ (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) !=
+ FALSE));
+}
+
+bool File::SetTimes(Time last_access_time, Time last_modified_time) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+
+ FILETIME last_access_filetime = last_access_time.ToFileTime();
+ FILETIME last_modified_filetime = last_modified_time.ToFileTime();
+ return (::SetFileTime(file_.Get(), NULL, &last_access_filetime,
+ &last_modified_filetime) != FALSE);
+}
+
+bool File::GetInfo(Info* info) {
+ ThreadRestrictions::AssertIOAllowed();
+ DCHECK(IsValid());
+
+ BY_HANDLE_FILE_INFORMATION file_info;
+ if (!GetFileInformationByHandle(file_.Get(), &file_info))
+ return false;
+
+ LARGE_INTEGER size;
+ size.HighPart = file_info.nFileSizeHigh;
+ size.LowPart = file_info.nFileSizeLow;
+ info->size = size.QuadPart;
+ info->is_directory =
+ (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ info->is_symbolic_link = false; // Windows doesn't have symbolic links.
+ info->last_modified = Time::FromFileTime(file_info.ftLastWriteTime);
+ info->last_accessed = Time::FromFileTime(file_info.ftLastAccessTime);
+ info->creation_time = Time::FromFileTime(file_info.ftCreationTime);
+ return true;
+}
+
+File::Error File::Lock() {
+ DCHECK(IsValid());
+ BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
+ if (!result)
+ return OSErrorToFileError(GetLastError());
+ return FILE_OK;
+}
+
+File::Error File::Unlock() {
+ DCHECK(IsValid());
+ BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
+ if (!result)
+ return OSErrorToFileError(GetLastError());
+ return FILE_OK;
+}
+
+File File::Duplicate() {
+ if (!IsValid())
+ return File();
+
+ HANDLE other_handle = nullptr;
+
+ if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle
+ GetPlatformFile(),
+ GetCurrentProcess(), // hTargetProcessHandle
+ &other_handle,
+ 0, // dwDesiredAccess ignored due to SAME_ACCESS
+ FALSE, // !bInheritHandle
+ DUPLICATE_SAME_ACCESS)) {
+ return File(OSErrorToFileError(GetLastError()));
+ }
+
+ File other(other_handle);
+ if (async())
+ other.async_ = true;
+ return other.Pass();
+}
+
+// Static.
+File::Error File::OSErrorToFileError(DWORD last_error) {
+ switch (last_error) {
+ case ERROR_SHARING_VIOLATION:
+ return FILE_ERROR_IN_USE;
+ case ERROR_FILE_EXISTS:
+ return FILE_ERROR_EXISTS;
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ return FILE_ERROR_NOT_FOUND;
+ case ERROR_ACCESS_DENIED:
+ return FILE_ERROR_ACCESS_DENIED;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ return FILE_ERROR_TOO_MANY_OPENED;
+ case ERROR_OUTOFMEMORY:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return FILE_ERROR_NO_MEMORY;
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ case ERROR_DISK_RESOURCES_EXHAUSTED:
+ return FILE_ERROR_NO_SPACE;
+ case ERROR_USER_MAPPED_FILE:
+ return FILE_ERROR_INVALID_OPERATION;
+ case ERROR_NOT_READY:
+ case ERROR_SECTOR_NOT_FOUND:
+ case ERROR_DEV_NOT_EXIST:
+ case ERROR_IO_DEVICE:
+ case ERROR_FILE_CORRUPT:
+ case ERROR_DISK_CORRUPT:
+ return FILE_ERROR_IO;
+ default:
+ UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
+ last_error);
+ return FILE_ERROR_FAILED;
+ }
+}
+
+void File::DoInitialize(const FilePath& name, uint32 flags) {
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(!IsValid());
DWORD disposition = 0;
@@ -102,272 +362,12 @@
}
}
-bool File::IsValid() const {
- return file_.IsValid();
-}
-
-PlatformFile File::GetPlatformFile() const {
- return file_.Get();
-}
-
-PlatformFile File::TakePlatformFile() {
- return file_.Take();
-}
-
-void File::Close() {
- if (file_.IsValid()) {
- base::ThreadRestrictions::AssertIOAllowed();
- file_.Close();
- }
-}
-
-int64 File::Seek(Whence whence, int64 offset) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
-
- LARGE_INTEGER distance, res;
- distance.QuadPart = offset;
- DWORD move_method = static_cast<DWORD>(whence);
- if (!SetFilePointerEx(file_.Get(), distance, &res, move_method))
- return -1;
- return res.QuadPart;
-}
-
-int File::Read(int64 offset, char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- DCHECK(!async_);
- if (size < 0)
- return -1;
-
- LARGE_INTEGER offset_li;
- offset_li.QuadPart = offset;
-
- OVERLAPPED overlapped = {0};
- overlapped.Offset = offset_li.LowPart;
- overlapped.OffsetHigh = offset_li.HighPart;
-
- DWORD bytes_read;
- if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped))
- return bytes_read;
- if (ERROR_HANDLE_EOF == GetLastError())
- return 0;
-
- return -1;
-}
-
-int File::ReadAtCurrentPos(char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- DCHECK(!async_);
- if (size < 0)
- return -1;
-
- DWORD bytes_read;
- if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL))
- return bytes_read;
- if (ERROR_HANDLE_EOF == GetLastError())
- return 0;
-
- return -1;
-}
-
-int File::ReadNoBestEffort(int64 offset, char* data, int size) {
- return Read(offset, data, size);
-}
-
-int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
- return ReadAtCurrentPos(data, size);
-}
-
-int File::Write(int64 offset, const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- DCHECK(!async_);
-
- LARGE_INTEGER offset_li;
- offset_li.QuadPart = offset;
-
- OVERLAPPED overlapped = {0};
- overlapped.Offset = offset_li.LowPart;
- overlapped.OffsetHigh = offset_li.HighPart;
-
- DWORD bytes_written;
- if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped))
- return bytes_written;
-
- return -1;
-}
-
-int File::WriteAtCurrentPos(const char* data, int size) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- DCHECK(!async_);
- if (size < 0)
- return -1;
-
- DWORD bytes_written;
- if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL))
- return bytes_written;
-
- return -1;
-}
-
-int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
- return WriteAtCurrentPos(data, size);
-}
-
-int64 File::GetLength() {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
- LARGE_INTEGER size;
- if (!::GetFileSizeEx(file_.Get(), &size))
- return -1;
-
- return static_cast<int64>(size.QuadPart);
-}
-
-bool File::SetLength(int64 length) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
-
- // Get the current file pointer.
- LARGE_INTEGER file_pointer;
- LARGE_INTEGER zero;
- zero.QuadPart = 0;
- if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT))
- return false;
-
- LARGE_INTEGER length_li;
- length_li.QuadPart = length;
- // If length > file size, SetFilePointerEx() should extend the file
- // with zeroes on all Windows standard file systems (NTFS, FATxx).
- if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN))
- return false;
-
- // Set the new file length and move the file pointer to its old position.
- // This is consistent with ftruncate()'s behavior, even when the file
- // pointer points to a location beyond the end of the file.
- // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not
- // promised by the interface (nor was promised by PlatformFile). See if this
- // implementation detail can be removed.
- return ((::SetEndOfFile(file_.Get()) != FALSE) &&
- (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) !=
- FALSE));
-}
-
-bool File::Flush() {
- base::ThreadRestrictions::AssertIOAllowed();
+bool File::DoFlush() {
+ ThreadRestrictions::AssertIOAllowed();
DCHECK(IsValid());
return ::FlushFileBuffers(file_.Get()) != FALSE;
}
-bool File::SetTimes(Time last_access_time, Time last_modified_time) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
-
- FILETIME last_access_filetime = last_access_time.ToFileTime();
- FILETIME last_modified_filetime = last_modified_time.ToFileTime();
- return (::SetFileTime(file_.Get(), NULL, &last_access_filetime,
- &last_modified_filetime) != FALSE);
-}
-
-bool File::GetInfo(Info* info) {
- base::ThreadRestrictions::AssertIOAllowed();
- DCHECK(IsValid());
-
- BY_HANDLE_FILE_INFORMATION file_info;
- if (!GetFileInformationByHandle(file_.Get(), &file_info))
- return false;
-
- LARGE_INTEGER size;
- size.HighPart = file_info.nFileSizeHigh;
- size.LowPart = file_info.nFileSizeLow;
- info->size = size.QuadPart;
- info->is_directory =
- (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
- info->is_symbolic_link = false; // Windows doesn't have symbolic links.
- info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime);
- info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime);
- info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime);
- return true;
-}
-
-File::Error base::File::Lock() {
- DCHECK(IsValid());
- BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
- if (!result)
- return OSErrorToFileError(GetLastError());
- return FILE_OK;
-}
-
-File::Error File::Unlock() {
- DCHECK(IsValid());
- BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
- if (!result)
- return OSErrorToFileError(GetLastError());
- return FILE_OK;
-}
-
-File File::Duplicate() {
- if (!IsValid())
- return File();
-
- HANDLE other_handle = nullptr;
-
- if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle
- GetPlatformFile(),
- GetCurrentProcess(), // hTargetProcessHandle
- &other_handle,
- 0, // dwDesiredAccess ignored due to SAME_ACCESS
- FALSE, // !bInheritHandle
- DUPLICATE_SAME_ACCESS)) {
- return File(OSErrorToFileError(GetLastError()));
- }
-
- File other(other_handle);
- if (async())
- other.async_ = true;
- return other.Pass();
-}
-
-// Static.
-File::Error File::OSErrorToFileError(DWORD last_error) {
- switch (last_error) {
- case ERROR_SHARING_VIOLATION:
- return FILE_ERROR_IN_USE;
- case ERROR_FILE_EXISTS:
- return FILE_ERROR_EXISTS;
- case ERROR_FILE_NOT_FOUND:
- case ERROR_PATH_NOT_FOUND:
- return FILE_ERROR_NOT_FOUND;
- case ERROR_ACCESS_DENIED:
- return FILE_ERROR_ACCESS_DENIED;
- case ERROR_TOO_MANY_OPEN_FILES:
- return FILE_ERROR_TOO_MANY_OPENED;
- case ERROR_OUTOFMEMORY:
- case ERROR_NOT_ENOUGH_MEMORY:
- return FILE_ERROR_NO_MEMORY;
- case ERROR_HANDLE_DISK_FULL:
- case ERROR_DISK_FULL:
- case ERROR_DISK_RESOURCES_EXHAUSTED:
- return FILE_ERROR_NO_SPACE;
- case ERROR_USER_MAPPED_FILE:
- return FILE_ERROR_INVALID_OPERATION;
- case ERROR_NOT_READY:
- case ERROR_SECTOR_NOT_FOUND:
- case ERROR_DEV_NOT_EXIST:
- case ERROR_IO_DEVICE:
- case ERROR_FILE_CORRUPT:
- case ERROR_DISK_CORRUPT:
- return FILE_ERROR_IO;
- default:
- UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
- last_error);
- return FILE_ERROR_FAILED;
- }
-}
-
void File::SetPlatformFile(PlatformFile file) {
file_.Set(file);
}
diff --git a/base/files/protect_file_posix.cc b/base/files/protect_file_posix.cc
deleted file mode 100644
index e4753c4..0000000
--- a/base/files/protect_file_posix.cc
+++ /dev/null
@@ -1,106 +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 "base/containers/hash_tables.h"
-#include "base/files/file.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/synchronization/lock.h"
-
-// These hooks provided for base::File perform additional sanity checks when
-// files are closed. These extra checks are hard to understand and maintain,
-// hence they are temporary. TODO(pasko): Remove these extra checks as soon as
-// crbug.com/424562 is fixed.
-//
-// Background:
-// 1. The browser process crashes if a call to close() provided by the C
-// library (i.e. close(3)) fails. This is done for security purposes. See
-// base/files/scoped_file.cc. When a crash like this happens, there is not
-// enough context in the minidump to triage the problem.
-// 2. base::File provides a good abstraction to prevent closing incorrect
-// file descriptors or double-closing. Closing non-owned file descriptors
-// would more likely happen from outside base::File and base::ScopedFD.
-//
-// These hooks intercept base::File operations to 'protect' file handles /
-// descriptors from accidental close(3) by other portions of the code being
-// linked into the browser. Also, this file provides an interceptor for the
-// close(3) itself, and requires to be linked with cooperation of
-// --Wl,--wrap=close (i.e. linker wrapping).
-//
-// Wrapping close(3) on all libraries can lead to confusion, particularly for
-// the libraries that do not use ::base (I am also looking at you,
-// crazy_linker). Instead two hooks are added to base::File, which are
-// implemented as no-op by default. This file should be linked into the Chrome
-// native binary(-ies) for a whitelist of targets where "file descriptor
-// protection" is useful.
-
-// With compilers other than GCC/Clang the wrapper is trivial. This is to avoid
-// overexercising mechanisms for overriding weak symbols.
-#if !defined(COMPILER_GCC)
-extern "C" {
-
-int __real_close(int fd);
-
-BASE_EXPORT int __wrap_close(int fd) {
- return __real_close(fd);
-}
-
-} // extern "C"
-
-#else // defined(COMPILER_GCC)
-
-namespace {
-
-// Protects the |g_protected_fd_set|.
-base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
-
-// Holds the set of all 'protected' file descriptors.
-base::LazyInstance<base::hash_set<int> >::Leaky g_protected_fd_set =
- LAZY_INSTANCE_INITIALIZER;
-
-bool IsFileDescriptorProtected(int fd) {
- base::AutoLock lock(*g_lock.Pointer());
- return g_protected_fd_set.Get().count(fd) != 0;
-}
-
-} // namespace
-
-namespace base {
-
-BASE_EXPORT void ProtectFileDescriptor(int fd) {
- base::AutoLock lock(g_lock.Get());
- CHECK(!g_protected_fd_set.Get().count(fd)) << "fd: " << fd;
- g_protected_fd_set.Get().insert(fd);
-}
-
-BASE_EXPORT void UnprotectFileDescriptor(int fd) {
- base::AutoLock lock(*g_lock.Pointer());
- CHECK(g_protected_fd_set.Get().erase(fd)) << "fd: " << fd;
-}
-
-} // namespace base
-
-extern "C" {
-
-int __real_close(int fd);
-
-BASE_EXPORT int __wrap_close(int fd) {
- // The crash happens here if a protected file descriptor was attempted to be
- // closed without first being unprotected. Unprotection happens only in
- // base::File. In other words this is an "early crash" as compared to the one
- // happening in scoped_file.cc.
- //
- // Getting an earlier crash provides a more useful stack trace (minidump)
- // allowing to debug deeper into the thread that freed the wrong resource.
- CHECK(!IsFileDescriptorProtected(fd)) << "fd: " << fd;
-
- // Crash by the same reason as in scoped_file.cc.
- PCHECK(0 == IGNORE_EINTR(__real_close(fd)));
- return 0;
-}
-
-} // extern "C"
-
-#endif // defined(COMPILER_GCC)
diff --git a/base/files/protect_file_posix.gypi b/base/files/protect_file_posix.gypi
deleted file mode 100644
index 017fd87..0000000
--- a/base/files/protect_file_posix.gypi
+++ /dev/null
@@ -1,31 +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.
-
-# Provides sanity-checks and early crashes on some improper use of posix file
-# descriptors. See protect_file_posix.cc for details.
-#
-# Usage:
-# {
-# 'target_name': 'libsomething',
-# 'type': 'shared_library', // Do *not* use it for static libraries.
-# 'includes': [
-# 'base/files/protect_file_posix.gypi',
-# ],
-# ...
-# }
-{
- 'conditions': [
- # In the component build the interceptors have to be declared with
- # non-hidden visibility, which is not desirable for the release build.
- # Disable the extra checks for the component build for simplicity.
- ['component != "shared_library"', {
- 'ldflags': [
- '-Wl,--wrap=close',
- ],
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:protect_file_posix',
- ],
- }],
- ],
-}
diff --git a/base/float_util.h b/base/float_util.h
deleted file mode 100644
index 9027310..0000000
--- a/base/float_util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_FLOAT_UTIL_H_
-#define BASE_FLOAT_UTIL_H_
-
-#include "build/build_config.h"
-
-#include <float.h>
-
-#include <cmath>
-
-namespace base {
-
-template <typename Float>
-inline bool IsFinite(const Float& number) {
-#if defined(OS_POSIX)
- return std::isfinite(number) != 0;
-#elif defined(OS_WIN)
- return _finite(number) != 0;
-#endif
-}
-
-template <typename Float>
-inline bool IsNaN(const Float& number) {
-#if defined(OS_POSIX)
- return std::isnan(number) != 0;
-#elif defined(OS_WIN)
- return _isnan(number) != 0;
-#endif
-}
-
-} // namespace base
-
-#endif // BASE_FLOAT_UTIL_H_
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
index f57bb39..f6e2c29 100644
--- a/base/i18n/file_util_icu.cc
+++ b/base/i18n/file_util_icu.cc
@@ -152,16 +152,15 @@
collator->setStrength(icu::Collator::TERTIARY);
#if defined(OS_WIN)
- return CompareString16WithCollator(collator.get(),
- WideToUTF16(a.value()), WideToUTF16(b.value())) == UCOL_LESS;
+ return CompareString16WithCollator(*collator, WideToUTF16(a.value()),
+ WideToUTF16(b.value())) == UCOL_LESS;
#elif defined(OS_POSIX)
// On linux, the file system encoding is not defined. We assume
// SysNativeMBToWide takes care of it.
return CompareString16WithCollator(
- collator.get(),
- WideToUTF16(SysNativeMBToWide(a.value().c_str())),
- WideToUTF16(SysNativeMBToWide(b.value().c_str()))) == UCOL_LESS;
+ *collator, WideToUTF16(SysNativeMBToWide(a.value().c_str())),
+ WideToUTF16(SysNativeMBToWide(b.value().c_str()))) == UCOL_LESS;
#else
#error Not implemented on your system
#endif
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc
index f1fdda7..76eaa62 100644
--- a/base/i18n/icu_util.cc
+++ b/base/i18n/icu_util.cc
@@ -10,6 +10,7 @@
#include <string>
+#include "base/debug/alias.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
@@ -48,7 +49,9 @@
// Assert that we are not called more than once. Even though calling this
// function isn't harmful (ICU can handle it), being called twice probably
// indicates a programming error.
+#if !defined(OS_NACL)
bool g_called_once = false;
+#endif
bool g_check_called_once = true;
#endif
}
@@ -81,6 +84,7 @@
#endif
+#if !defined(OS_NACL)
bool InitializeICU() {
#if !defined(NDEBUG)
DCHECK(!g_check_called_once || !g_called_once);
@@ -127,6 +131,10 @@
#if defined(OS_WIN)
// The data file will be in the same directory as the current module.
bool path_ok = PathService::Get(base::DIR_MODULE, &data_path);
+ wchar_t tmp_buffer[_MAX_PATH] = {0};
+ wcscpy_s(tmp_buffer, data_path.value().c_str());
+ base::debug::Alias(tmp_buffer);
+ CHECK(path_ok); // TODO(scottmg): http://crbug.com/445616
#elif defined(OS_ANDROID)
bool path_ok = PathService::Get(base::DIR_ANDROID_APP_DATA, &data_path);
#else
@@ -137,6 +145,14 @@
#endif
DCHECK(path_ok);
data_path = data_path.AppendASCII(kIcuDataFileName);
+
+#if defined(OS_WIN)
+ // TODO(scottmg): http://crbug.com/445616
+ wchar_t tmp_buffer2[_MAX_PATH] = {0};
+ wcscpy_s(tmp_buffer2, data_path.value().c_str());
+ base::debug::Alias(tmp_buffer2);
+#endif
+
#else
// Assume it is in the framework bundle's Resources directory.
base::ScopedCFTypeRef<CFStringRef> data_file_name(
@@ -149,15 +165,22 @@
}
#endif // OS check
if (!mapped_file.Initialize(data_path)) {
+#if defined(OS_WIN)
+ CHECK(false); // TODO(scottmg): http://crbug.com/445616
+#endif
LOG(ERROR) << "Couldn't mmap " << data_path.AsUTF8Unsafe();
return false;
}
}
UErrorCode err = U_ZERO_ERROR;
udata_setCommonData(const_cast<uint8*>(mapped_file.data()), &err);
+#if defined(OS_WIN)
+ CHECK(err == U_ZERO_ERROR); // TODO(scottmg): http://crbug.com/445616
+#endif
return err == U_ZERO_ERROR;
#endif
}
+#endif
void AllowMultipleInitializeCallsForTesting() {
#if !defined(NDEBUG)
diff --git a/base/i18n/icu_util.h b/base/i18n/icu_util.h
index 5094cb0..e9f7c3d 100644
--- a/base/i18n/icu_util.h
+++ b/base/i18n/icu_util.h
@@ -14,9 +14,11 @@
BASE_I18N_EXPORT extern const char kIcuDataFileName[];
+#if !defined(OS_NACL)
// Call this function to load ICU's data tables for the current process. This
// function should be called before ICU is used.
BASE_I18N_EXPORT bool InitializeICU();
+#endif
#if defined(OS_ANDROID)
// Android uses a file descriptor passed by browser process to initialize ICU
diff --git a/base/i18n/string_compare.cc b/base/i18n/string_compare.cc
index 1ac7284..2851e7d 100644
--- a/base/i18n/string_compare.cc
+++ b/base/i18n/string_compare.cc
@@ -12,12 +12,11 @@
// Compares the character data stored in two different string16 strings by
// specified Collator instance.
-UCollationResult CompareString16WithCollator(const icu::Collator* collator,
+UCollationResult CompareString16WithCollator(const icu::Collator& collator,
const string16& lhs,
const string16& rhs) {
- DCHECK(collator);
UErrorCode error = U_ZERO_ERROR;
- UCollationResult result = collator->compare(
+ UCollationResult result = collator.compare(
static_cast<const UChar*>(lhs.c_str()), static_cast<int>(lhs.length()),
static_cast<const UChar*>(rhs.c_str()), static_cast<int>(rhs.length()),
error);
diff --git a/base/i18n/string_compare.h b/base/i18n/string_compare.h
index 158c93b..5fcc5fe 100644
--- a/base/i18n/string_compare.h
+++ b/base/i18n/string_compare.h
@@ -17,10 +17,10 @@
namespace i18n {
// Compares the two strings using the specified collator.
-BASE_I18N_EXPORT UCollationResult CompareString16WithCollator(
- const icu::Collator* collator,
- const string16& lhs,
- const string16& rhs);
+BASE_I18N_EXPORT UCollationResult
+CompareString16WithCollator(const icu::Collator& collator,
+ const string16& lhs,
+ const string16& rhs);
} // namespace i18n
} // namespace base
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc
index d42b1a3..e9a27bc 100644
--- a/base/json/json_parser.cc
+++ b/base/json/json_parser.cc
@@ -4,7 +4,8 @@
#include "base/json/json_parser.h"
-#include "base/float_util.h"
+#include <cmath>
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
@@ -872,7 +873,7 @@
double num_double;
if (base::StringToDouble(num_string.as_string(), &num_double) &&
- IsFinite(num_double)) {
+ std::isfinite(num_double)) {
return new FundamentalValue(num_double);
}
diff --git a/base/json/json_value_converter.h b/base/json/json_value_converter.h
index c4bfe61..f94d46e 100644
--- a/base/json/json_value_converter.h
+++ b/base/json/json_value_converter.h
@@ -123,8 +123,7 @@
value_converter_(converter) {
}
- virtual bool ConvertField(
- const base::Value& value, StructType* dst) const override {
+ bool ConvertField(const base::Value& value, StructType* dst) const override {
return value_converter_->Convert(value, &(dst->*field_pointer_));
}
@@ -202,8 +201,7 @@
ValueFieldConverter(ConvertFunc convert_func)
: convert_func_(convert_func) {}
- virtual bool Convert(const base::Value& value,
- FieldType* field) const override {
+ bool Convert(const base::Value& value, FieldType* field) const override {
return convert_func_(&value, field);
}
@@ -221,8 +219,7 @@
CustomFieldConverter(ConvertFunc convert_func)
: convert_func_(convert_func) {}
- virtual bool Convert(const base::Value& value,
- FieldType* field) const override {
+ bool Convert(const base::Value& value, FieldType* field) const override {
std::string string_value;
return value.GetAsString(&string_value) &&
convert_func_(string_value, field);
@@ -239,8 +236,7 @@
public:
NestedValueConverter() {}
- virtual bool Convert(
- const base::Value& value, NestedType* field) const override {
+ bool Convert(const base::Value& value, NestedType* field) const override {
return converter_.Convert(value, field);
}
@@ -254,8 +250,8 @@
public:
RepeatedValueConverter() {}
- virtual bool Convert(
- const base::Value& value, ScopedVector<Element>* field) const override {
+ bool Convert(const base::Value& value,
+ ScopedVector<Element>* field) const override {
const base::ListValue* list = NULL;
if (!value.GetAsList(&list)) {
// The field is not a list.
@@ -290,8 +286,8 @@
public:
RepeatedMessageConverter() {}
- virtual bool Convert(const base::Value& value,
- ScopedVector<NestedType>* field) const override {
+ bool Convert(const base::Value& value,
+ ScopedVector<NestedType>* field) const override {
const base::ListValue* list = NULL;
if (!value.GetAsList(&list))
return false;
@@ -327,8 +323,8 @@
RepeatedCustomValueConverter(ConvertFunc convert_func)
: convert_func_(convert_func) {}
- virtual bool Convert(const base::Value& value,
- ScopedVector<NestedType>* field) const override {
+ bool Convert(const base::Value& value,
+ ScopedVector<NestedType>* field) const override {
const base::ListValue* list = NULL;
if (!value.GetAsList(&list))
return false;
diff --git a/base/logging_win.h b/base/logging_win.h
index 38508a3..aa48e22 100644
--- a/base/logging_win.h
+++ b/base/logging_win.h
@@ -61,8 +61,8 @@
protected:
// Overridden to manipulate the log level on ETW control callbacks.
- virtual void OnEventsEnabled();
- virtual void OnEventsDisabled();
+ void OnEventsEnabled() override;
+ void OnEventsDisabled() override;
private:
LogEventProvider();
diff --git a/base/mac/close_nocancel.cc b/base/mac/close_nocancel.cc
index 134f7ac..8971e73 100644
--- a/base/mac/close_nocancel.cc
+++ b/base/mac/close_nocancel.cc
@@ -28,12 +28,14 @@
//
// This file operates by providing a close function with the non-$NOCANCEL
// symbol name expected for the compilation environment as set by <unistd.h>
-// and <sys/cdefs.h> (the DARWIN_ALIAS_C macro). That function calls the
-// $NOCANCEL variant, which is resolved from libsyscall. By linking with this
-// version of close prior to the libsyscall version, close's implementation is
-// overridden.
+// and <sys/cdefs.h> (the DARWIN_ALIAS_C macro). That name is set by an asm
+// label on the declaration of the close function, so the definition of that
+// function receives that name. The function calls the $NOCANCEL variant, which
+// is resolved from libsyscall. By linking with this version of close prior to
+// the libsyscall version, close's implementation is overridden.
#include <sys/cdefs.h>
+#include <unistd.h>
// If the non-cancelable variants of all system calls have already been
// chosen, do nothing.
@@ -41,37 +43,26 @@
extern "C" {
-#if __DARWIN_UNIX03 && !__DARWIN_ONLY_UNIX_CONFORMANCE
+#if !__DARWIN_ONLY_UNIX_CONFORMANCE
-// When there's a choice between UNIX2003 and pre-UNIX2003 and UNIX2003 has
-// been chosen:
-#define close_interface close$UNIX2003
-#define close_implementation close$NOCANCEL$UNIX2003
-
-#elif !__DARWIN_UNIX03 && !__DARWIN_ONLY_UNIX_CONFORMANCE
-
-// When there's a choice between UNIX2003 and pre-UNIX2003 and pre-UNIX2003
-// has been chosen. There's no close$NOCANCEL symbol in this case, so use
-// close$NOCANCEL$UNIX2003 as the implementation. It does the same thing
-// that close$NOCANCEL would do.
-#define close_interface close
+// When there's a choice between UNIX2003 and pre-UNIX2003. There's no
+// close$NOCANCEL symbol in this case, so use close$NOCANCEL$UNIX2003 as the
+// implementation. It does the same thing that close$NOCANCEL would do.
#define close_implementation close$NOCANCEL$UNIX2003
#else // __DARWIN_ONLY_UNIX_CONFORMANCE
// When only UNIX2003 is supported:
-#define close_interface close
#define close_implementation close$NOCANCEL
#endif
int close_implementation(int fd);
-int close_interface(int fd) {
+int close(int fd) {
return close_implementation(fd);
}
-#undef close_interface
#undef close_implementation
} // extern "C"
diff --git a/base/md5.cc b/base/md5.cc
index 6227ee6..72c774d 100644
--- a/base/md5.cc
+++ b/base/md5.cc
@@ -23,27 +23,28 @@
#include "base/md5.h"
-#include "base/basictypes.h"
+#include <stddef.h>
namespace {
struct Context {
- uint32 buf[4];
- uint32 bits[2];
- unsigned char in[64];
+ uint32_t buf[4];
+ uint32_t bits[2];
+ uint8_t in[64];
};
/*
* Note: this code is harmless on little-endian machines.
*/
-void byteReverse(unsigned char *buf, unsigned longs) {
- uint32 t;
- do {
- t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
- ((unsigned)buf[1]<<8 | buf[0]);
- *(uint32 *)buf = t;
- buf += 4;
- } while (--longs);
+void byteReverse(uint8_t* buf, unsigned longs) {
+ do {
+ uint32_t temp = static_cast<uint32_t>(
+ static_cast<unsigned>(buf[3]) << 8 |
+ buf[2]) << 16 |
+ (static_cast<unsigned>(buf[1]) << 8 | buf[0]);
+ *reinterpret_cast<uint32_t*>(buf) = temp;
+ buf += 4;
+ } while (--longs);
}
/* The four core functions - F1 is optimized somewhat */
@@ -56,93 +57,93 @@
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+ (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
-void MD5Transform(uint32 buf[4], const uint32 in[16]) {
- register uint32 a, b, c, d;
+void MD5Transform(uint32_t buf[4], const uint32_t in[16]) {
+ uint32_t a, b, c, d;
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
}
} // namespace
@@ -154,13 +155,13 @@
* initialization constants.
*/
void MD5Init(MD5Context* context) {
- struct Context *ctx = (struct Context *)context;
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
+ struct Context* ctx = reinterpret_cast<struct Context*>(context);
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
}
/*
@@ -168,51 +169,49 @@
* of bytes.
*/
void MD5Update(MD5Context* context, const StringPiece& data) {
- const unsigned char* inbuf = (const unsigned char*)data.data();
- size_t len = data.size();
- struct Context *ctx = (struct Context *)context;
- const unsigned char* buf = (const unsigned char*)inbuf;
- uint32 t;
+ struct Context* ctx = reinterpret_cast<struct Context*>(context);
+ const uint8_t* buf = reinterpret_cast<const uint8_t*>(data.data());
+ size_t len = data.size();
- /* Update bitcount */
+ /* Update bitcount */
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += static_cast<uint32>(len >> 29);
+ uint32_t t = ctx->bits[0];
+ if ((ctx->bits[0] = t + (static_cast<uint32_t>(len) << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += static_cast<uint32_t>(len >> 29);
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
- /* Handle any leading odd-sized chunks */
+ /* Handle any leading odd-sized chunks */
- if (t) {
- unsigned char *p = (unsigned char *)ctx->in + t;
+ if (t) {
+ uint8_t* p = static_cast<uint8_t*>(ctx->in + t);
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += t;
- len -= t;
- }
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+ buf += t;
+ len -= t;
+ }
- /* Process data in 64-byte chunks */
+ /* Process data in 64-byte chunks */
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += 64;
- len -= 64;
- }
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+ buf += 64;
+ len -= 64;
+ }
- /* Handle any remaining bytes of data. */
+ /* Handle any remaining bytes of data. */
- memcpy(ctx->in, buf, len);
+ memcpy(ctx->in, buf, len);
}
/*
@@ -220,48 +219,46 @@
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(MD5Digest* digest, MD5Context* context) {
- struct Context *ctx = (struct Context *)context;
- unsigned count;
- unsigned char *p;
+ struct Context* ctx = reinterpret_cast<struct Context*>(context);
+ unsigned count;
+ uint8_t* p;
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
- byteReverse(ctx->in, 14);
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
- /* Append length in bits and transform */
- memcpy(&ctx->in[14 * sizeof(ctx->bits[0])],
- &ctx->bits[0],
- sizeof(ctx->bits[0]));
- memcpy(&ctx->in[15 * sizeof(ctx->bits[1])],
- &ctx->bits[1],
- sizeof(ctx->bits[1]));
+ /* Append length in bits and transform */
+ memcpy(&ctx->in[14 * sizeof(ctx->bits[0])], &ctx->bits[0],
+ sizeof(ctx->bits[0]));
+ memcpy(&ctx->in[15 * sizeof(ctx->bits[1])], &ctx->bits[1],
+ sizeof(ctx->bits[1]));
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- byteReverse((unsigned char *)ctx->buf, 4);
- memcpy(digest->a, ctx->buf, 16);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+ MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+ byteReverse(reinterpret_cast<uint8_t*>(ctx->buf), 4);
+ memcpy(digest->a, ctx->buf, 16);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
void MD5IntermediateFinal(MD5Digest* digest, const MD5Context* context) {
@@ -278,11 +275,10 @@
std::string ret;
ret.resize(32);
- int j = 0;
- for (int i = 0; i < 16; i ++) {
- int a = digest.a[i];
- ret[j++] = zEncode[(a>>4)&0xf];
- ret[j++] = zEncode[a & 0xf];
+ for (int i = 0, j = 0; i < 16; i++, j += 2) {
+ uint8_t a = digest.a[i];
+ ret[j] = zEncode[(a >> 4) & 0xf];
+ ret[j + 1] = zEncode[a & 0xf];
}
return ret;
}
@@ -290,8 +286,7 @@
void MD5Sum(const void* data, size_t length, MD5Digest* digest) {
MD5Context ctx;
MD5Init(&ctx);
- MD5Update(&ctx,
- StringPiece(reinterpret_cast<const char*>(data), length));
+ MD5Update(&ctx, StringPiece(reinterpret_cast<const char*>(data), length));
MD5Final(digest, &ctx);
}
diff --git a/base/md5.h b/base/md5.h
index 0a87fcf..0b4cbce 100644
--- a/base/md5.h
+++ b/base/md5.h
@@ -5,6 +5,8 @@
#ifndef BASE_MD5_H_
#define BASE_MD5_H_
+#include <stdint.h>
+
#include "base/base_export.h"
#include "base/strings/string_piece.h"
@@ -35,17 +37,13 @@
// The output of an MD5 operation.
struct MD5Digest {
- unsigned char a[16];
+ uint8_t a[16];
};
// Used for storing intermediate data during an MD5 computation. Callers
// should not access the data.
typedef char MD5Context[88];
-// Computes the MD5 sum of the given data buffer with the given length.
-// The given 'digest' structure will be filled with the result data.
-BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest);
-
// Initializes the given MD5 context structure for subsequent calls to
// MD5Update().
BASE_EXPORT void MD5Init(MD5Context* context);
@@ -67,6 +65,10 @@
// Converts a digest into human-readable hexadecimal.
BASE_EXPORT std::string MD5DigestToBase16(const MD5Digest& digest);
+// Computes the MD5 sum of the given data buffer with the given length.
+// The given 'digest' structure will be filled with the result data.
+BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest);
+
// Returns the MD5 (in hexadecimal) of a string.
BASE_EXPORT std::string MD5String(const StringPiece& str);
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn
index a0608e8..bd864ca 100644
--- a/base/memory/BUILD.gn
+++ b/base/memory/BUILD.gn
@@ -16,6 +16,8 @@
"manual_constructor.h",
"memory_pressure_listener.cc",
"memory_pressure_listener.h",
+ "memory_pressure_monitor.cc",
+ "memory_pressure_monitor.h",
"raw_scoped_refptr_mismatch_checker.h",
"ref_counted.cc",
"ref_counted.h",
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h
index a0882cc..fc189e7 100644
--- a/base/memory/discardable_memory.h
+++ b/base/memory/discardable_memory.h
@@ -52,8 +52,13 @@
virtual void Unlock() = 0;
// Returns the memory address held by this object. The object must be locked
- // before calling this. Otherwise, this will cause a DCHECK error.
- virtual void* Memory() const = 0;
+ // before calling this.
+ virtual void* data() const = 0;
+
+ // Handy method to simplify calling data() with a reinterpret_cast.
+ template<typename T> T* data_as() const {
+ return reinterpret_cast<T*>(data());
+ }
};
} // namespace base
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 49e93cd..830d6b9 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -325,22 +325,6 @@
return true;
}
-bool DiscardableSharedMemory::PurgeAndTruncate(Time current_time) {
- if (!Purge(current_time))
- return false;
-
-#if defined(OS_POSIX)
- // Truncate shared memory to size of SharedState.
- SharedMemoryHandle handle = shared_memory_.handle();
- if (SharedMemory::IsHandleValid(handle)) {
- if (HANDLE_EINTR(ftruncate(handle.fd, sizeof(SharedState))) != 0)
- DPLOG(ERROR) << "ftruncate() failed";
- }
-#endif
-
- return true;
-}
-
bool DiscardableSharedMemory::IsMemoryResident() const {
DCHECK(shared_memory_.memory());
@@ -357,6 +341,26 @@
mapped_size_ = 0;
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+void DiscardableSharedMemory::Shrink() {
+#if defined(OS_POSIX)
+ SharedMemoryHandle handle = shared_memory_.handle();
+ if (!SharedMemory::IsHandleValid(handle))
+ return;
+
+ // Truncate shared memory to size of SharedState.
+ if (HANDLE_EINTR(
+ ftruncate(handle.fd, AlignToPageSize(sizeof(SharedState)))) != 0) {
+ DPLOG(ERROR) << "ftruncate() failed";
+ return;
+ }
+ mapped_size_ = 0;
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+#endif
+
Time DiscardableSharedMemory::Now() const {
return Time::Now();
}
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
index e3b437c..892d556 100644
--- a/base/memory/discardable_shared_memory.h
+++ b/base/memory/discardable_shared_memory.h
@@ -15,6 +15,12 @@
#include <set>
#endif
+// Define DISCARDABLE_SHARED_MEMORY_SHRINKING if platform supports shrinking
+// of discardable shared memory segments.
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#define DISCARDABLE_SHARED_MEMORY_SHRINKING
+#endif
+
namespace base {
// Platform abstraction for discardable shared memory.
@@ -93,12 +99,6 @@
// each call.
bool Purge(Time current_time);
- // Purge and release as much memory as possible to the OS.
- // Note: The amount of memory that can be released to the OS is platform
- // specific. Best case, all but one page is released. Worst case, nothing
- // is released.
- bool PurgeAndTruncate(Time current_time);
-
// Returns true if memory is still resident.
bool IsMemoryResident() const;
@@ -116,6 +116,12 @@
return shared_memory_.ShareToProcess(process_handle, new_handle);
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+ // Release as much memory as possible to the OS. The change in size will
+ // be reflected by the return value of mapped_size().
+ void Shrink();
+#endif
+
private:
// Virtual for tests.
virtual Time Now() const;
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
index 74d19a6..ae7235d 100644
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -311,5 +311,21 @@
EXPECT_EQ(0u, memory.mapped_size());
}
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+TEST(DiscardableSharedMemoryTest, Shrink) {
+ const uint32 kDataSize = 1024;
+
+ TestDiscardableSharedMemory memory;
+ bool rv = memory.CreateAndMap(kDataSize);
+ ASSERT_TRUE(rv);
+
+ EXPECT_NE(0u, memory.mapped_size());
+
+ // Mapped size should be 0 after shrinking memory segment.
+ memory.Shrink();
+ EXPECT_EQ(0u, memory.mapped_size());
+}
+#endif
+
} // namespace
} // namespace base
diff --git a/base/memory/manual_constructor.h b/base/memory/manual_constructor.h
index 9275f73..56081a1 100644
--- a/base/memory/manual_constructor.h
+++ b/base/memory/manual_constructor.h
@@ -18,6 +18,7 @@
#include <stddef.h>
+#include "base/compiler_specific.h"
#include "base/memory/aligned_memory.h"
namespace base {
@@ -33,11 +34,7 @@
// Support users creating arrays of ManualConstructor<>s. This ensures that
// the array itself has the correct alignment.
static void* operator new[](size_t size) {
-#if defined(COMPILER_MSVC)
- return AlignedAlloc(size, __alignof(Type));
-#else
- return AlignedAlloc(size, __alignof__(Type));
-#endif
+ return AlignedAlloc(size, ALIGNOF(Type));
}
static void operator delete[](void* mem) {
AlignedFree(mem);
@@ -56,56 +53,9 @@
inline Type& operator*() { return *get(); }
inline const Type& operator*() const { return *get(); }
- // You can pass up to eight constructor arguments as arguments of Init().
- inline void Init() {
- new(space_.void_data()) Type;
- }
-
- template <typename T1>
- inline void Init(const T1& p1) {
- new(space_.void_data()) Type(p1);
- }
-
- template <typename T1, typename T2>
- inline void Init(const T1& p1, const T2& p2) {
- new(space_.void_data()) Type(p1, p2);
- }
-
- template <typename T1, typename T2, typename T3>
- inline void Init(const T1& p1, const T2& p2, const T3& p3) {
- new(space_.void_data()) Type(p1, p2, p3);
- }
-
- template <typename T1, typename T2, typename T3, typename T4>
- inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
- new(space_.void_data()) Type(p1, p2, p3, p4);
- }
-
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
- inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
- const T5& p5) {
- new(space_.void_data()) Type(p1, p2, p3, p4, p5);
- }
-
- template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
- inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
- const T5& p5, const T6& p6) {
- new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6);
- }
-
- template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7>
- inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
- const T5& p5, const T6& p6, const T7& p7) {
- new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7);
- }
-
- template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8>
- inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
- const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
- new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
+ template <typename... Ts>
+ inline void Init(const Ts&... params) {
+ new(space_.void_data()) Type(params...);
}
inline void Destroy() {
@@ -113,11 +63,7 @@
}
private:
-#if defined(COMPILER_MSVC)
- AlignedMemory<sizeof(Type), __alignof(Type)> space_;
-#else
- AlignedMemory<sizeof(Type), __alignof__(Type)> space_;
-#endif
+ AlignedMemory<sizeof(Type), ALIGNOF(Type)> space_;
};
} // namespace base
diff --git a/base/memory/memory_pressure_monitor.cc b/base/memory/memory_pressure_monitor.cc
new file mode 100644
index 0000000..00633f1
--- /dev/null
+++ b/base/memory/memory_pressure_monitor.cc
@@ -0,0 +1,31 @@
+// 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/memory/memory_pressure_monitor.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace {
+
+MemoryPressureMonitor* g_monitor = nullptr;
+
+} // namespace
+
+MemoryPressureMonitor::MemoryPressureMonitor() {
+ DCHECK(!g_monitor);
+ g_monitor = this;
+}
+
+MemoryPressureMonitor::~MemoryPressureMonitor() {
+ DCHECK(g_monitor);
+ g_monitor = nullptr;
+}
+
+// static
+MemoryPressureMonitor* MemoryPressureMonitor::Get() {
+ return g_monitor;
+}
+
+} // namespace base
diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h
new file mode 100644
index 0000000..9aeeaca
--- /dev/null
+++ b/base/memory/memory_pressure_monitor.h
@@ -0,0 +1,39 @@
+// 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 BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
+#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
+
+#include "base/base_export.h"
+#include "base/memory/memory_pressure_listener.h"
+
+namespace base {
+
+// Declares the interface for a MemoryPressureMonitor. There are multiple
+// OS specific implementations of this class. An instance of the memory
+// pressure observer is created at the process level, tracks memory usage, and
+// pushes memory state change notifications to the static function
+// base::MemoryPressureListener::NotifyMemoryPressure. This is turn notifies
+// all MemoryPressureListener instances via a callback.
+class BASE_EXPORT MemoryPressureMonitor {
+ public:
+ using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
+
+ // Return the singleton MemoryPressureMonitor.
+ static MemoryPressureMonitor* Get();
+
+ // Returns the currently observed memory pressure.
+ virtual MemoryPressureLevel GetCurrentPressureLevel() const = 0;
+
+ protected:
+ MemoryPressureMonitor();
+ virtual ~MemoryPressureMonitor();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
+};
+
+} // namespace base
+
+#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
index 219437e..5f94b4c 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -14,6 +14,7 @@
#ifndef NDEBUG
#include "base/logging.h"
#endif
+#include "base/move.h"
#include "base/threading/thread_collision_warner.h"
#include "build/build_config.h"
@@ -264,6 +265,7 @@
//
template <class T>
class scoped_refptr {
+ TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr)
public:
typedef T element_type;
@@ -286,6 +288,11 @@
AddRef(ptr_);
}
+ template <typename U>
+ scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
+ r.ptr_ = nullptr;
+ }
+
~scoped_refptr() {
if (ptr_)
Release(ptr_);
@@ -323,6 +330,17 @@
return *this = r.get();
}
+ scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
+ scoped_refptr<T>(r.Pass()).swap(*this);
+ return *this;
+ }
+
+ template <typename U>
+ scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
+ scoped_refptr<T>(r.Pass()).swap(*this);
+ return *this;
+ }
+
void swap(T** pp) {
T* p = ptr_;
ptr_ = *pp;
@@ -334,6 +352,8 @@
}
private:
+ template <typename U> friend class scoped_refptr;
+
// Allow scoped_refptr<T> to be used in boolean expressions, but not
// implicitly convertible to a real bool (which is dangerous).
//
diff --git a/base/memory/ref_counted_delete_on_message_loop.h b/base/memory/ref_counted_delete_on_message_loop.h
index 7b898ac..139a1ed 100644
--- a/base/memory/ref_counted_delete_on_message_loop.h
+++ b/base/memory/ref_counted_delete_on_message_loop.h
@@ -8,7 +8,9 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+// TODO(ricea): Remove the following include once all callers have been fixed.
#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
namespace base {
@@ -18,7 +20,7 @@
// Sample usage:
// class Foo : public RefCountedDeleteOnMessageLoop<Foo> {
//
-// Foo(const scoped_refptr<MessageLoopProxy>& loop)
+// Foo(const scoped_refptr<SingleThreadTaskRunner>& loop)
// : RefCountedDeleteOnMessageLoop<Foo>(loop) {
// ...
// }
@@ -33,9 +35,14 @@
template <class T>
class RefCountedDeleteOnMessageLoop : public subtle::RefCountedThreadSafeBase {
public:
+ // This constructor will accept a MessageL00pProxy object, but new code should
+ // prefer a SingleThreadTaskRunner. A SingleThreadTaskRunner for the
+ // MessageLoop on the current thread can be acquired by calling
+ // MessageLoop::current()->task_runner().
RefCountedDeleteOnMessageLoop(
- const scoped_refptr<MessageLoopProxy>& proxy) : proxy_(proxy) {
- DCHECK(proxy_.get());
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+ : task_runner_(task_runner) {
+ DCHECK(task_runner_.get());
}
void AddRef() const {
@@ -53,13 +60,13 @@
void DestructOnMessageLoop() const {
const T* t = static_cast<const T*>(this);
- if (proxy_->BelongsToCurrentThread())
+ if (task_runner_->BelongsToCurrentThread())
delete t;
else
- proxy_->DeleteSoon(FROM_HERE, t);
+ task_runner_->DeleteSoon(FROM_HERE, t);
}
- scoped_refptr<MessageLoopProxy> proxy_;
+ scoped_refptr<SingleThreadTaskRunner> task_runner_;
private:
DISALLOW_COPY_AND_ASSIGN(RefCountedDeleteOnMessageLoop);
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc
index f75cd38..6f8e599 100644
--- a/base/memory/ref_counted_unittest.cc
+++ b/base/memory/ref_counted_unittest.cc
@@ -40,19 +40,71 @@
static bool was_destroyed() { return was_destroyed_; }
- void SelfDestruct() { self_ptr_ = NULL; }
+ static void reset_was_destroyed() { was_destroyed_ = false; }
+
+ scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
private:
friend class base::RefCounted<ScopedRefPtrToSelf>;
~ScopedRefPtrToSelf() { was_destroyed_ = true; }
static bool was_destroyed_;
-
- scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
};
bool ScopedRefPtrToSelf::was_destroyed_ = false;
+class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
+ public:
+ ScopedRefPtrCountBase() { ++constructor_count_; }
+
+ static int constructor_count() { return constructor_count_; }
+
+ static int destructor_count() { return destructor_count_; }
+
+ static void reset_count() {
+ constructor_count_ = 0;
+ destructor_count_ = 0;
+ }
+
+ protected:
+ virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
+
+ private:
+ friend class base::RefCounted<ScopedRefPtrCountBase>;
+
+ static int constructor_count_;
+ static int destructor_count_;
+};
+
+int ScopedRefPtrCountBase::constructor_count_ = 0;
+int ScopedRefPtrCountBase::destructor_count_ = 0;
+
+class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
+ public:
+ ScopedRefPtrCountDerived() { ++constructor_count_; }
+
+ static int constructor_count() { return constructor_count_; }
+
+ static int destructor_count() { return destructor_count_; }
+
+ static void reset_count() {
+ constructor_count_ = 0;
+ destructor_count_ = 0;
+ }
+
+ protected:
+ ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
+
+ private:
+ friend class base::RefCounted<ScopedRefPtrCountDerived>;
+
+ static int constructor_count_;
+ static int destructor_count_;
+};
+
+int ScopedRefPtrCountDerived::constructor_count_ = 0;
+int ScopedRefPtrCountDerived::destructor_count_ = 0;
+
} // end namespace
TEST(RefCountedUnitTest, TestSelfAssignment) {
@@ -66,10 +118,24 @@
CheckDerivedMemberAccess check;
}
-TEST(RefCountedUnitTest, ScopedRefPtrToSelf) {
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
+ ScopedRefPtrToSelf::reset_was_destroyed();
+
ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
- check->SelfDestruct();
+ check->self_ptr_ = nullptr;
+ EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
+ ScopedRefPtrToSelf::reset_was_destroyed();
+
+ ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
+ EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
+ // Releasing |check->self_ptr_| will delete |check|.
+ // The move assignment operator must assign |check->self_ptr_| first then
+ // release |check->self_ptr_|.
+ check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
}
@@ -113,3 +179,284 @@
EXPECT_EQ(p1, p2);
EXPECT_EQ(p2, p1);
}
+
+TEST(RefCountedUnitTest, SelfMoveAssignment) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p = p.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p.get());
+
+ // p goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment1) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2;
+
+ p2 = p1.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment2) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1;
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p2 = p1.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw2, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDerived) {
+ ScopedRefPtrCountBase::reset_count();
+ ScopedRefPtrCountDerived::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ {
+ ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
+ scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+ EXPECT_EQ(raw2, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructor) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructorDerived) {
+ ScopedRefPtrCountBase::reset_count();
+ ScopedRefPtrCountDerived::reset_count();
+
+ {
+ ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
+ scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw1, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
index 6e5a4d8..6fe5706 100644
--- a/base/memory/shared_memory_unittest.cc
+++ b/base/memory/shared_memory_unittest.cc
@@ -101,10 +101,10 @@
class MultipleLockThread : public PlatformThread::Delegate {
public:
explicit MultipleLockThread(int id) : id_(id) {}
- virtual ~MultipleLockThread() {}
+ ~MultipleLockThread() override {}
// PlatformThread::Delegate interface.
- virtual void ThreadMain() override {
+ void ThreadMain() override {
const uint32 kDataSize = sizeof(int);
SharedMemoryHandle handle = NULL;
{
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index ccf79c0..ddde6bb 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -425,7 +425,7 @@
public:
DispatcherImpl() : dispatch_count_(0) {}
- virtual uint32_t Dispatch(const NativeEvent& msg) override {
+ uint32_t Dispatch(const NativeEvent& msg) override {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
// Do not count WM_TIMER since it is not what we post and it will cause
@@ -489,8 +489,9 @@
public:
TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
- virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
- DWORD bytes_transfered, DWORD error);
+ void OnIOCompleted(MessageLoopForIO::IOContext* context,
+ DWORD bytes_transfered,
+ DWORD error) override;
void Init();
void WaitForIO();
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc
index d52025a..b5b1fb7 100644
--- a/base/message_loop/message_pump_libevent.cc
+++ b/base/message_loop/message_pump_libevent.cc
@@ -15,6 +15,7 @@
#include "base/observer_list.h"
#include "base/posix/eintr_wrapper.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/libevent/event.h"
#if defined(OS_MACOSX)
@@ -274,6 +275,9 @@
delayed_work_time_ = TimeTicks();
}
}
+
+ if (!keep_running_)
+ break;
}
}
@@ -341,6 +345,8 @@
WeakPtr<FileDescriptorWatcher> controller =
static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr();
DCHECK(controller.get());
+ TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification",
+ "fd", fd);
MessagePumpLibevent* pump = controller->pump();
pump->processed_io_events_ = true;
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc
index 1058ee8..65d7217 100644
--- a/base/message_loop/message_pump_libevent_unittest.cc
+++ b/base/message_loop/message_pump_libevent_unittest.cc
@@ -7,9 +7,14 @@
#include <unistd.h>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/posix/eintr_wrapper.h"
#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/synchronization/waitable_event_watcher.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libevent/event.h"
@@ -19,7 +24,7 @@
class MessagePumpLibeventTest : public testing::Test {
protected:
MessagePumpLibeventTest()
- : ui_loop_(MessageLoop::TYPE_UI),
+ : ui_loop_(new MessageLoop(MessageLoop::TYPE_UI)),
io_thread_("MessagePumpLibeventTestIOThread") {}
~MessagePumpLibeventTest() override {}
@@ -38,7 +43,6 @@
PLOG(ERROR) << "close";
}
- MessageLoop* ui_loop() { return &ui_loop_; }
MessageLoopForIO* io_loop() const {
return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
}
@@ -50,9 +54,9 @@
}
int pipefds_[2];
+ scoped_ptr<MessageLoop> ui_loop_;
private:
- MessageLoop ui_loop_;
Thread io_thread_;
};
@@ -194,6 +198,69 @@
OnLibeventNotification(pump.get(), &watcher);
}
+void FatalClosure() {
+ FAIL() << "Reached fatal closure.";
+}
+
+class QuitWatcher : public BaseWatcher {
+ public:
+ QuitWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller,
+ RunLoop* run_loop)
+ : BaseWatcher(controller), run_loop_(run_loop) {}
+ ~QuitWatcher() override {}
+
+ void OnFileCanReadWithoutBlocking(int /* fd */) override {
+ // Post a fatal closure to the MessageLoop before we quit it.
+ MessageLoop::current()->PostTask(FROM_HERE, Bind(&FatalClosure));
+
+ // Now quit the MessageLoop.
+ run_loop_->Quit();
+ }
+
+ private:
+ RunLoop* run_loop_; // weak
+};
+
+void WriteFDWrapper(const int fd,
+ const char* buf,
+ int size,
+ WaitableEvent* event) {
+ ASSERT_TRUE(WriteFileDescriptor(fd, buf, size));
+}
+
+// Tests that MessagePumpLibevent quits immediately when it is quit from
+// libevent's event_base_loop().
+TEST_F(MessagePumpLibeventTest, QuitWatcher) {
+ // Delete the old MessageLoop so that we can manage our own one here.
+ ui_loop_.reset();
+
+ MessagePumpLibevent* pump = new MessagePumpLibevent; // owned by |loop|.
+ MessageLoop loop(make_scoped_ptr(pump));
+ RunLoop run_loop;
+ MessagePumpLibevent::FileDescriptorWatcher controller;
+ QuitWatcher delegate(&controller, &run_loop);
+ WaitableEvent event(false /* manual_reset */, false /* initially_signaled */);
+ WaitableEventWatcher watcher;
+
+ // Tell the pump to watch the pipe.
+ pump->WatchFileDescriptor(pipefds_[0], false, MessagePumpLibevent::WATCH_READ,
+ &controller, &delegate);
+
+ // Make the IO thread wait for |event| before writing to pipefds[1].
+ const char buf = 0;
+ const WaitableEventWatcher::EventCallback write_fd_task =
+ Bind(&WriteFDWrapper, pipefds_[1], &buf, 1);
+ io_loop()->PostTask(FROM_HERE,
+ Bind(IgnoreResult(&WaitableEventWatcher::StartWatching),
+ Unretained(&watcher), &event, write_fd_task));
+
+ // Queue |event| to signal on |loop|.
+ loop.PostTask(FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&event)));
+
+ // Now run the MessageLoop.
+ run_loop.Run();
+}
+
} // namespace
} // namespace base
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index 8226495..27b47e1 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -53,6 +53,10 @@
state_ = previous_state;
}
+void MessagePumpWin::Run(Delegate* delegate) {
+ RunWithDispatcher(delegate, NULL);
+}
+
void MessagePumpWin::Quit() {
DCHECK(state_);
state_->should_quit = true;
@@ -472,6 +476,9 @@
DCHECK(port_.IsValid());
}
+MessagePumpForIO::~MessagePumpForIO() {
+}
+
void MessagePumpForIO::ScheduleWork() {
if (InterlockedExchange(&have_work_, 1))
return; // Someone else continued the pumping.
diff --git a/base/message_loop/message_pump_win.h b/base/message_loop/message_pump_win.h
index b257317..00f1287 100644
--- a/base/message_loop/message_pump_win.h
+++ b/base/message_loop/message_pump_win.h
@@ -25,14 +25,13 @@
class BASE_EXPORT MessagePumpWin : public MessagePump {
public:
MessagePumpWin() : have_work_(0), state_(NULL) {}
- virtual ~MessagePumpWin() {}
// Like MessagePump::Run, but MSG objects are routed through dispatcher.
void RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher);
// MessagePump methods:
- virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
- virtual void Quit();
+ void Run(Delegate* delegate) override;
+ void Quit() override;
protected:
struct RunState {
@@ -115,18 +114,18 @@
static const int kMessageFilterCode = 0x5001;
MessagePumpForUI();
- virtual ~MessagePumpForUI();
+ ~MessagePumpForUI() override;
// MessagePump methods:
- virtual void ScheduleWork();
- virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
+ void ScheduleWork() override;
+ void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
private:
static LRESULT CALLBACK WndProcThunk(HWND window_handle,
UINT message,
WPARAM wparam,
LPARAM lparam);
- virtual void DoRunLoop();
+ void DoRunLoop() override;
void InitMessageWnd();
void WaitForWork();
void HandleWorkMessage();
@@ -267,11 +266,11 @@
};
MessagePumpForIO();
- virtual ~MessagePumpForIO() {}
+ ~MessagePumpForIO() override;
// MessagePump methods:
- virtual void ScheduleWork();
- virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
+ void ScheduleWork() override;
+ void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
// Register the handler to be used when asynchronous IO for the given file
// completes. The registration persists as long as |file_handle| is valid, so
@@ -311,7 +310,7 @@
bool has_valid_io_context;
};
- virtual void DoRunLoop();
+ void DoRunLoop() override;
void WaitForWork();
bool MatchCompletedIOItem(IOHandler* filter, IOItem* item);
bool GetIOItem(DWORD timeout, IOItem* item);
diff --git a/base/metrics/BUILD.gn b/base/metrics/BUILD.gn
index 0202637..845ac4f 100644
--- a/base/metrics/BUILD.gn
+++ b/base/metrics/BUILD.gn
@@ -12,8 +12,8 @@
"histogram.h",
"histogram_base.cc",
"histogram_base.h",
- "histogram_delta_serialization.",
"histogram_delta_serialization.cc",
+ "histogram_delta_serialization.h",
"histogram_flattener.h",
"histogram_macros.h",
"histogram_samples.cc",
diff --git a/base/move.h b/base/move.h
index 06f3f32..87dc52d 100644
--- a/base/move.h
+++ b/base/move.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/compiler_specific.h"
-
#ifndef BASE_MOVE_H_
#define BASE_MOVE_H_
+#include "base/compiler_specific.h"
+
// Macro with the boilerplate that makes a type move-only in C++03.
//
// USAGE
@@ -219,11 +219,16 @@
#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
private: \
- type(type&); \
- void operator=(type&); \
+ type(const type&); \
+ void operator=(const type&); \
public: \
type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \
typedef void MoveOnlyTypeForCPP03; \
private:
+#define TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
+ public: \
+ type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \
+ private:
+
#endif // BASE_MOVE_H_
diff --git a/base/move_unittest.cc b/base/move_unittest.cc
new file mode 100644
index 0000000..1f4ce84
--- /dev/null
+++ b/base/move_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/move.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MoveOnly {
+ MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(MoveOnly)
+
+ public:
+ MoveOnly() {}
+
+ MoveOnly(MoveOnly&& other) {}
+ MoveOnly& operator=(MoveOnly&& other) { return *this; }
+};
+
+class Container {
+ public:
+ Container() = default;
+ Container(const Container& other) = default;
+ Container& operator=(const Container& other) = default;
+
+ Container(Container&& other) { value_ = other.value_.Pass(); }
+
+ Container& operator=(Container&& other) {
+ value_ = other.value_.Pass();
+ return *this;
+ }
+
+ private:
+ MoveOnly value_;
+};
+
+Container GetContainerRvalue() {
+ Container x;
+ return x;
+}
+
+TEST(MoveTest, CopyableContainerCanBeMoved) {
+ // Container should be move-constructible and move-assignable.
+ Container y = GetContainerRvalue();
+ y = GetContainerRvalue();
+}
+
+} // namespace
diff --git a/base/native_library_ios.mm b/base/native_library_ios.mm
new file mode 100644
index 0000000..030c171
--- /dev/null
+++ b/base/native_library_ios.mm
@@ -0,0 +1,40 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/native_library.h"
+
+#include "base/logging.h"
+
+namespace base {
+
+std::string NativeLibraryLoadError::ToString() const {
+ return message;
+}
+
+// static
+NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
+ NativeLibraryLoadError* error) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+// static
+void UnloadNativeLibrary(NativeLibrary library) {
+ NOTIMPLEMENTED();
+ DCHECK(!library);
+}
+
+// static
+void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
+ const char* name) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+// static
+string16 GetNativeLibraryName(const string16& name) {
+ return name;
+}
+
+} // namespace base
diff --git a/base/observer_list.h b/base/observer_list.h
index f7b9267..9ea344d 100644
--- a/base/observer_list.h
+++ b/base/observer_list.h
@@ -143,17 +143,18 @@
template <class ObserverType>
ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() {
if (!list_.get())
- return NULL;
+ return nullptr;
ListType& observers = list_->observers_;
// Advance if the current element is null
size_t max_index = std::min(max_index_, observers.size());
while (index_ < max_index && !observers[index_])
++index_;
- return index_ < max_index ? observers[index_++] : NULL;
+ return index_ < max_index ? observers[index_++] : nullptr;
}
template <class ObserverType>
void ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) {
+ DCHECK(obs);
if (std::find(observers_.begin(), observers_.end(), obs)
!= observers_.end()) {
NOTREACHED() << "Observers can only be added once!";
@@ -164,11 +165,12 @@
template <class ObserverType>
void ObserverListBase<ObserverType>::RemoveObserver(ObserverType* obs) {
+ DCHECK(obs);
typename ListType::iterator it =
std::find(observers_.begin(), observers_.end(), obs);
if (it != observers_.end()) {
if (notify_depth_) {
- *it = 0;
+ *it = nullptr;
} else {
observers_.erase(it);
}
@@ -190,7 +192,7 @@
if (notify_depth_) {
for (typename ListType::iterator it = observers_.begin();
it != observers_.end(); ++it) {
- *it = 0;
+ *it = nullptr;
}
} else {
observers_.clear();
@@ -200,8 +202,8 @@
template <class ObserverType>
void ObserverListBase<ObserverType>::Compact() {
observers_.erase(
- std::remove(observers_.begin(), observers_.end(),
- static_cast<ObserverType*>(NULL)), observers_.end());
+ std::remove(observers_.begin(), observers_.end(), nullptr),
+ observers_.end());
}
template <class ObserverType, bool check_empty = false>
@@ -233,7 +235,7 @@
ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \
&observer_list); \
ObserverType* obs; \
- while ((obs = it_inside_observer_macro.GetNext()) != NULL) \
+ while ((obs = it_inside_observer_macro.GetNext()) != nullptr) \
obs->func; \
} \
} while (0)
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index 46ce880..5205a5a 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -111,7 +111,7 @@
if (!base::MessageLoop::current())
return;
- ObserverList<ObserverType>* list = NULL;
+ ObserverList<ObserverType>* list = nullptr;
base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
{
base::AutoLock lock(list_lock_);
@@ -128,8 +128,8 @@
// If the observer to be removed is in the list, RemoveObserver MUST
// be called from the same thread which called AddObserver.
void RemoveObserver(ObserverType* obs) {
- ObserverListContext* context = NULL;
- ObserverList<ObserverType>* list = NULL;
+ ObserverListContext* context = nullptr;
+ ObserverList<ObserverType>* list = nullptr;
base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
{
base::AutoLock lock(list_lock_);
@@ -230,7 +230,7 @@
{
typename ObserverList<ObserverType>::Iterator it(&context->list);
ObserverType* obs;
- while ((obs = it.GetNext()) != NULL)
+ while ((obs = it.GetNext()) != nullptr)
method.Run(obs);
}
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 636aa83..ea916b1 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -71,7 +71,7 @@
adder(1) {
}
- virtual void Observe(int x) override {
+ void Observe(int x) override {
if (!added) {
added = true;
observer_list->AddObserver(&adder);
@@ -94,7 +94,7 @@
public:
AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify)
: list_(list),
- loop_(NULL),
+ loop_(nullptr),
in_list_(false),
start_(Time::Now()),
count_observes_(0),
diff --git a/base/prefs/pref_member.h b/base/prefs/pref_member.h
index 078be95..9b140d1 100644
--- a/base/prefs/pref_member.h
+++ b/base/prefs/pref_member.h
@@ -264,9 +264,9 @@
}
protected:
- virtual ~Internal() {}
+ ~Internal() override {}
- virtual BASE_PREFS_EXPORT bool UpdateValueInternal(
+ BASE_PREFS_EXPORT bool UpdateValueInternal(
const base::Value& value) const override;
// We cache the value of the pref so we don't have to keep walking the pref
@@ -277,8 +277,8 @@
DISALLOW_COPY_AND_ASSIGN(Internal);
};
- virtual Internal* internal() const override { return internal_.get(); }
- virtual void CreateInternal() const override { internal_ = new Internal(); }
+ Internal* internal() const override { return internal_.get(); }
+ void CreateInternal() const override { internal_ = new Internal(); }
// This method is used to do the actual sync with pref of the specified type.
void BASE_PREFS_EXPORT UpdatePref(const ValueType& value);
diff --git a/base/prefs/pref_registry.cc b/base/prefs/pref_registry.cc
index 69f0494..74f4b52 100644
--- a/base/prefs/pref_registry.cc
+++ b/base/prefs/pref_registry.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/prefs/default_pref_store.h"
#include "base/prefs/pref_store.h"
+#include "base/stl_util.h"
#include "base/values.h"
PrefRegistry::PrefRegistry()
@@ -16,6 +17,13 @@
PrefRegistry::~PrefRegistry() {
}
+uint32 PrefRegistry::GetRegistrationFlags(const std::string& pref_name) const {
+ const auto& it = registration_flags_.find(pref_name);
+ if (it == registration_flags_.end())
+ return NO_REGISTRATION_FLAGS;
+ return it->second;
+}
+
scoped_refptr<PrefStore> PrefRegistry::defaults() {
return defaults_.get();
}
@@ -41,13 +49,18 @@
}
void PrefRegistry::RegisterPreference(const std::string& path,
- base::Value* default_value) {
+ base::Value* default_value,
+ uint32 flags) {
base::Value::Type orig_type = default_value->GetType();
DCHECK(orig_type != base::Value::TYPE_NULL &&
orig_type != base::Value::TYPE_BINARY) <<
"invalid preference type: " << orig_type;
DCHECK(!defaults_->GetValue(path, NULL)) <<
"Trying to register a previously registered pref: " << path;
+ DCHECK(!ContainsKey(registration_flags_, path)) <<
+ "Trying to register a previously registered pref: " << path;
defaults_->SetDefaultValue(path, make_scoped_ptr(default_value));
+ if (flags != NO_REGISTRATION_FLAGS)
+ registration_flags_[path] = flags;
}
diff --git a/base/prefs/pref_registry.h b/base/prefs/pref_registry.h
index a500b6e..cc5804e 100644
--- a/base/prefs/pref_registry.h
+++ b/base/prefs/pref_registry.h
@@ -5,6 +5,7 @@
#ifndef BASE_PREFS_PREF_REGISTRY_H_
#define BASE_PREFS_PREF_REGISTRY_H_
+#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/prefs/base_prefs_export.h"
#include "base/prefs/pref_value_map.h"
@@ -27,10 +28,26 @@
// also work, but this is being deprecated.
class BASE_PREFS_EXPORT PrefRegistry : public base::RefCounted<PrefRegistry> {
public:
+ // Registration flags that can be specified which impact how the pref will
+ // behave or be stored. This will be passed in a bitmask when the pref is
+ // registered. Subclasses of PrefRegistry can specify their own flags. Care
+ // must be taken to ensure none of these overlap with the flags below.
+ enum PrefRegistrationFlags {
+ // No flags are specified.
+ NO_REGISTRATION_FLAGS = 0,
+
+ // The first 8 bits are reserved for subclasses of PrefRegistry to use.
+ };
+
typedef PrefValueMap::const_iterator const_iterator;
+ typedef base::hash_map<std::string, uint32> PrefRegistrationFlagsMap;
PrefRegistry();
+ // Retrieve the set of registration flags for the given preference. The return
+ // value is a bitmask of PrefRegistrationFlags.
+ uint32 GetRegistrationFlags(const std::string& pref_name) const;
+
// Gets the registered defaults.
scoped_refptr<PrefStore> defaults();
@@ -47,11 +64,17 @@
friend class base::RefCounted<PrefRegistry>;
virtual ~PrefRegistry();
- // Used by subclasses to register a default value for a preference.
- void RegisterPreference(const std::string& path, base::Value* default_value);
+ // Used by subclasses to register a default value and registration flags for
+ // a preference. |flags| is a bitmask of |PrefRegistrationFlags|.
+ void RegisterPreference(const std::string& path,
+ base::Value* default_value,
+ uint32 flags);
scoped_refptr<DefaultPrefStore> defaults_;
+ // A map of pref name to a bitmask of PrefRegistrationFlags.
+ PrefRegistrationFlagsMap registration_flags_;
+
private:
DISALLOW_COPY_AND_ASSIGN(PrefRegistry);
};
diff --git a/base/prefs/pref_registry_simple.cc b/base/prefs/pref_registry_simple.cc
index fa679dc..93c2686 100644
--- a/base/prefs/pref_registry_simple.cc
+++ b/base/prefs/pref_registry_simple.cc
@@ -16,51 +16,146 @@
void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
bool default_value) {
- RegisterPreference(path, new base::FundamentalValue(default_value));
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
int default_value) {
- RegisterPreference(path, new base::FundamentalValue(default_value));
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
double default_value) {
- RegisterPreference(path, new base::FundamentalValue(default_value));
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterStringPref(const std::string& path,
const std::string& default_value) {
- RegisterPreference(path, new base::StringValue(default_value));
+ RegisterPrefAndNotify(path, new base::StringValue(default_value),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterFilePathPref(
const std::string& path,
const base::FilePath& default_value) {
- RegisterPreference(path, new base::StringValue(default_value.value()));
+ RegisterPrefAndNotify(path, new base::StringValue(default_value.value()),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterListPref(const std::string& path) {
- RegisterPreference(path, new base::ListValue());
+ RegisterPrefAndNotify(path, new base::ListValue(), NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterListPref(const std::string& path,
base::ListValue* default_value) {
- RegisterPreference(path, default_value);
+ RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path) {
- RegisterPreference(path, new base::DictionaryValue());
+ RegisterPrefAndNotify(path, new base::DictionaryValue(),
+ NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterDictionaryPref(
const std::string& path,
base::DictionaryValue* default_value) {
- RegisterPreference(path, default_value);
+ RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS);
}
void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
int64 default_value) {
- RegisterPreference(
- path, new base::StringValue(base::Int64ToString(default_value)));
+ RegisterPrefAndNotify(
+ path, new base::StringValue(base::Int64ToString(default_value)),
+ NO_REGISTRATION_FLAGS);
+}
+
+void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
+ uint64 default_value) {
+ RegisterPrefAndNotify(
+ path, new base::StringValue(base::Uint64ToString(default_value)),
+ NO_REGISTRATION_FLAGS);
+}
+
+void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
+ bool default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
+ int default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
+ double default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterStringPref(const std::string& path,
+ const std::string& default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::StringValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterFilePathPref(
+ const std::string& path,
+ const base::FilePath& default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::StringValue(default_value.value()),
+ flags);
+}
+
+void PrefRegistrySimple::RegisterListPref(const std::string& path,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::ListValue(), flags);
+}
+
+void PrefRegistrySimple::RegisterListPref(const std::string& path,
+ base::ListValue* default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, default_value, flags);
+}
+
+void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, new base::DictionaryValue(), flags);
+}
+
+void PrefRegistrySimple::RegisterDictionaryPref(
+ const std::string& path,
+ base::DictionaryValue* default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(path, default_value, flags);
+}
+
+void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
+ int64 default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(
+ path, new base::StringValue(base::Int64ToString(default_value)), flags);
+}
+
+void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
+ uint64 default_value,
+ uint32 flags) {
+ RegisterPrefAndNotify(
+ path, new base::StringValue(base::Uint64ToString(default_value)), flags);
+}
+
+void PrefRegistrySimple::OnPrefRegistered(const std::string& path,
+ base::Value* default_value,
+ uint32 flags) {
+}
+
+void PrefRegistrySimple::RegisterPrefAndNotify(const std::string& path,
+ base::Value* default_value,
+ uint32 flags) {
+ RegisterPreference(path, default_value, flags);
+ OnPrefRegistered(path, default_value, flags);
}
diff --git a/base/prefs/pref_registry_simple.h b/base/prefs/pref_registry_simple.h
index 73ae216..6b69e30 100644
--- a/base/prefs/pref_registry_simple.h
+++ b/base/prefs/pref_registry_simple.h
@@ -35,9 +35,48 @@
void RegisterDictionaryPref(const std::string& path,
base::DictionaryValue* default_value);
void RegisterInt64Pref(const std::string& path, int64 default_value);
+ void RegisterUint64Pref(const std::string&, uint64 default_value);
+
+ // Versions of registration functions that accept PrefRegistrationFlags.
+ // |flags| is a bitmask of PrefRegistrationFlags.
+ void RegisterBooleanPref(const std::string&,
+ bool default_value,
+ uint32 flags);
+ void RegisterIntegerPref(const std::string&, int default_value, uint32 flags);
+ void RegisterDoublePref(const std::string&,
+ double default_value,
+ uint32 flags);
+ void RegisterStringPref(const std::string&,
+ const std::string& default_value,
+ uint32 flags);
+ void RegisterFilePathPref(const std::string&,
+ const base::FilePath& default_value,
+ uint32 flags);
+ void RegisterListPref(const std::string&, uint32 flags);
+ void RegisterDictionaryPref(const std::string&, uint32 flags);
+ void RegisterListPref(const std::string&,
+ base::ListValue* default_value,
+ uint32 flags);
+ void RegisterDictionaryPref(const std::string&,
+ base::DictionaryValue* default_value,
+ uint32 flags);
+ void RegisterInt64Pref(const std::string&, int64 default_value, uint32 flags);
+ void RegisterUint64Pref(const std::string&,
+ uint64 default_value,
+ uint32 flags);
+
+ protected:
+ ~PrefRegistrySimple() override;
+
+ // Allows subclasses to hook into pref registration.
+ virtual void OnPrefRegistered(const std::string&,
+ base::Value* default_value,
+ uint32 flags);
private:
- ~PrefRegistrySimple() override;
+ void RegisterPrefAndNotify(const std::string&,
+ base::Value* default_value,
+ uint32 flags);
DISALLOW_COPY_AND_ASSIGN(PrefRegistrySimple);
};
diff --git a/base/prefs/pref_value_map.cc b/base/prefs/pref_value_map.cc
index cafc1d8..5f2dc50 100644
--- a/base/prefs/pref_value_map.cc
+++ b/base/prefs/pref_value_map.cc
@@ -4,6 +4,8 @@
#include "base/prefs/pref_value_map.h"
+#include <map>
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
@@ -18,51 +20,49 @@
bool PrefValueMap::GetValue(const std::string& key,
const base::Value** value) const {
const Map::const_iterator entry = prefs_.find(key);
- if (entry != prefs_.end()) {
- if (value)
- *value = entry->second;
- return true;
- }
+ if (entry == prefs_.end())
+ return false;
- return false;
+ if (value)
+ *value = entry->second;
+ return true;
}
bool PrefValueMap::GetValue(const std::string& key, base::Value** value) {
const Map::const_iterator entry = prefs_.find(key);
- if (entry != prefs_.end()) {
- if (value)
- *value = entry->second;
- return true;
- }
+ if (entry == prefs_.end())
+ return false;
- return false;
+ if (value)
+ *value = entry->second;
+ return true;
}
bool PrefValueMap::SetValue(const std::string& key, base::Value* value) {
DCHECK(value);
+ auto result = prefs_.insert(std::make_pair(key, value));
+ if (result.second)
+ return true;
+
scoped_ptr<base::Value> value_ptr(value);
- const Map::iterator entry = prefs_.find(key);
- if (entry != prefs_.end()) {
- if (base::Value::Equals(entry->second, value))
- return false;
- delete entry->second;
- entry->second = value_ptr.release();
- } else {
- prefs_[key] = value_ptr.release();
- }
+ const Map::iterator& entry = result.first;
+ if (base::Value::Equals(entry->second, value))
+ return false;
+
+ delete entry->second;
+ entry->second = value_ptr.release();
return true;
}
bool PrefValueMap::RemoveValue(const std::string& key) {
const Map::iterator entry = prefs_.find(key);
- if (entry != prefs_.end()) {
- delete entry->second;
- prefs_.erase(entry);
- return true;
- }
+ if (entry == prefs_.end())
+ return false;
- return false;
+ delete entry->second;
+ prefs_.erase(entry);
+ return true;
}
void PrefValueMap::Clear() {
@@ -91,7 +91,7 @@
bool PrefValueMap::GetBoolean(const std::string& key,
bool* value) const {
- const base::Value* stored_value = NULL;
+ const base::Value* stored_value = nullptr;
return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value);
}
@@ -101,7 +101,7 @@
bool PrefValueMap::GetString(const std::string& key,
std::string* value) const {
- const base::Value* stored_value = NULL;
+ const base::Value* stored_value = nullptr;
return GetValue(key, &stored_value) && stored_value->GetAsString(value);
}
@@ -111,7 +111,7 @@
}
bool PrefValueMap::GetInteger(const std::string& key, int* value) const {
- const base::Value* stored_value = NULL;
+ const base::Value* stored_value = nullptr;
return GetValue(key, &stored_value) && stored_value->GetAsInteger(value);
}
@@ -128,10 +128,15 @@
std::vector<std::string>* differing_keys) const {
differing_keys->clear();
+ // Put everything into ordered maps.
+ std::map<std::string, base::Value*> this_prefs(prefs_.begin(), prefs_.end());
+ std::map<std::string, base::Value*> other_prefs(other->prefs_.begin(),
+ other->prefs_.end());
+
// Walk over the maps in lockstep, adding everything that is different.
- Map::const_iterator this_pref(prefs_.begin());
- Map::const_iterator other_pref(other->prefs_.begin());
- while (this_pref != prefs_.end() && other_pref != other->prefs_.end()) {
+ auto this_pref(this_prefs.begin());
+ auto other_pref(other_prefs.begin());
+ while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) {
const int diff = this_pref->first.compare(other_pref->first);
if (diff == 0) {
if (!this_pref->second->Equals(other_pref->second))
@@ -148,8 +153,8 @@
}
// Add the remaining entries.
- for ( ; this_pref != prefs_.end(); ++this_pref)
+ for ( ; this_pref != this_prefs.end(); ++this_pref)
differing_keys->push_back(this_pref->first);
- for ( ; other_pref != other->prefs_.end(); ++other_pref)
+ for ( ; other_pref != other_prefs.end(); ++other_pref)
differing_keys->push_back(other_pref->first);
}
diff --git a/base/prefs/pref_value_map.h b/base/prefs/pref_value_map.h
index 2db18ab..12b30c6 100644
--- a/base/prefs/pref_value_map.h
+++ b/base/prefs/pref_value_map.h
@@ -5,11 +5,11 @@
#ifndef BASE_PREFS_PREF_VALUE_MAP_H_
#define BASE_PREFS_PREF_VALUE_MAP_H_
-#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
#include "base/prefs/base_prefs_export.h"
namespace base {
@@ -19,8 +19,9 @@
// A generic string to value map used by the PrefStore implementations.
class BASE_PREFS_EXPORT PrefValueMap {
public:
- typedef std::map<std::string, base::Value*>::iterator iterator;
- typedef std::map<std::string, base::Value*>::const_iterator const_iterator;
+ using Map = base::hash_map<std::string, base::Value*>;
+ using iterator = Map::iterator;
+ using const_iterator = Map::const_iterator;
PrefValueMap();
virtual ~PrefValueMap();
@@ -81,8 +82,6 @@
std::vector<std::string>* differing_keys) const;
private:
- typedef std::map<std::string, base::Value*> Map;
-
Map prefs_;
DISALLOW_COPY_AND_ASSIGN(PrefValueMap);
diff --git a/base/process/kill.cc b/base/process/kill.cc
index a647d96..5d8ba6a 100644
--- a/base/process/kill.cc
+++ b/base/process/kill.cc
@@ -15,7 +15,7 @@
NamedProcessIterator iter(executable_name, filter);
while (const ProcessEntry* entry = iter.NextProcessEntry()) {
Process process = Process::Open(entry->pid());
- result &= KillProcess(process.Handle(), exit_code, true);
+ result &= process.Terminate(exit_code, true);
}
return result;
}
diff --git a/base/process/kill.h b/base/process/kill.h
index df0d95e..af00b03 100644
--- a/base/process/kill.h
+++ b/base/process/kill.h
@@ -45,12 +45,6 @@
int exit_code,
const ProcessFilter* filter);
-// Attempts to kill the process identified by the given process
-// entry structure, giving it the specified exit code. If |wait| is true, wait
-// for the process to be actually terminated before returning.
-// Returns true if this is successful, false otherwise.
-BASE_EXPORT bool KillProcess(ProcessHandle process, int exit_code, bool wait);
-
#if defined(OS_POSIX)
// Attempts to kill the process group identified by |process_group_id|. Returns
// true on success.
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index 298486b..0e303c6 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -15,7 +15,6 @@
#include "base/posix/eintr_wrapper.h"
#include "base/process/process_iterator.h"
#include "base/synchronization/waitable_event.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/platform_thread.h"
namespace base {
@@ -69,61 +68,6 @@
} // namespace
#if !defined(OS_NACL_NONSFI)
-// Attempts to kill the process identified by the given process
-// entry structure. Ignores specified exit_code; posix can't force that.
-// Returns true if this is successful, false otherwise.
-bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
- DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
- if (process_id <= 1)
- return false;
- bool result = kill(process_id, SIGTERM) == 0;
- if (result && wait) {
- int tries = 60;
-
- if (RunningOnValgrind()) {
- // Wait for some extra time when running under Valgrind since the child
- // processes may take some time doing leak checking.
- tries *= 2;
- }
-
- unsigned sleep_ms = 4;
-
- // The process may not end immediately due to pending I/O
- bool exited = false;
- while (tries-- > 0) {
- pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
- if (pid == process_id) {
- exited = true;
- break;
- }
- if (pid == -1) {
- if (errno == ECHILD) {
- // The wait may fail with ECHILD if another process also waited for
- // the same pid, causing the process state to get cleaned up.
- exited = true;
- break;
- }
- DPLOG(ERROR) << "Error waiting for process " << process_id;
- }
-
- usleep(sleep_ms * 1000);
- const unsigned kMaxSleepMs = 1000;
- if (sleep_ms < kMaxSleepMs)
- sleep_ms *= 2;
- }
-
- // If we're waiting and the child hasn't died by now, force it
- // with a SIGKILL.
- if (!exited)
- result = kill(process_id, SIGKILL) == 0;
- }
-
- if (!result)
- DPLOG(ERROR) << "Unable to terminate process " << process_id;
-
- return result;
-}
-
bool KillProcessGroup(ProcessHandle process_group_id) {
bool result = kill(-1 * process_group_id, SIGKILL) == 0;
if (!result)
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 3c93047..0da3a26 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -38,12 +38,12 @@
class TimerExpiredTask : public win::ObjectWatcher::Delegate {
public:
explicit TimerExpiredTask(Process process);
- ~TimerExpiredTask();
+ ~TimerExpiredTask() override;
void TimedOut();
// MessageLoop::Watcher -----------------------------------------------------
- virtual void OnObjectSignaled(HANDLE object);
+ void OnObjectSignaled(HANDLE object) override;
private:
void KillProcess();
@@ -81,7 +81,7 @@
// terminates. We just care that it eventually terminates, and that's what
// TerminateProcess should do for us. Don't check for the result code since
// it fails quite often. This should be investigated eventually.
- base::KillProcess(process_.Handle(), kProcessKilledExitCode, false);
+ process_.Terminate(kProcessKilledExitCode, false);
// Now, just cleanup as if the process exited normally.
OnObjectSignaled(process_.Handle());
@@ -89,18 +89,6 @@
} // namespace
-bool KillProcess(ProcessHandle process, int exit_code, bool wait) {
- bool result = (TerminateProcess(process, exit_code) != FALSE);
- if (result && wait) {
- // The process may not end immediately due to pending I/O
- if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000))
- DPLOG(ERROR) << "Error waiting for process exit";
- } else if (!result) {
- DPLOG(ERROR) << "Unable to terminate process";
- }
- return result;
-}
-
TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
DWORD tmp_exit_code = 0;
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index c2bd295..ebc19b8 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -219,7 +219,8 @@
if (0 == AssignProcessToJobObject(options.job_handle,
process_info.process_handle())) {
DLOG(ERROR) << "Could not AssignProcessToObject.";
- KillProcess(process_info.process_handle(), kProcessKilledExitCode, true);
+ Process scoped_process(process_info.TakeProcessHandle());
+ scoped_process.Terminate(kProcessKilledExitCode, true);
return Process();
}
diff --git a/base/process/memory.cc b/base/process/memory.cc
index 8542dc5..133a72a 100644
--- a/base/process/memory.cc
+++ b/base/process/memory.cc
@@ -2,10 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/debug/alias.h"
+#include "base/logging.h"
#include "base/process/memory.h"
namespace base {
+namespace {
+
+// Breakpad server classifies base::`anonymous namespace'::OnNoMemory as
+// out-of-memory crash.
+NOINLINE void OnNoMemory(size_t size) {
+ size_t tmp_size = size;
+ base::debug::Alias(&tmp_size);
+ LOG(FATAL) << "Out of memory. size=" << tmp_size;
+}
+
+} // namespace
+
+void TerminateBecauseOutOfMemory(size_t size) {
+ OnNoMemory(size);
+}
+
// Defined in memory_mac.mm for Mac.
#if !defined(OS_MACOSX)
diff --git a/base/process/memory.h b/base/process/memory.h
index 100d9c7..da27151 100644
--- a/base/process/memory.h
+++ b/base/process/memory.h
@@ -39,6 +39,10 @@
// Turns on process termination if memory runs out.
BASE_EXPORT void EnableTerminationOnOutOfMemory();
+// Terminates process. Should be called only for out of memory errors.
+// Crash reporting classifies such crashes as OOM.
+BASE_EXPORT void TerminateBecauseOutOfMemory(size_t size);
+
#if defined(OS_WIN)
// Returns the module handle to which an address belongs. The reference count
// of the module is not incremented.
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm
index 0f0414b..4d719f8 100644
--- a/base/process/memory_mac.mm
+++ b/base/process/memory_mac.mm
@@ -131,7 +131,7 @@
size_t size) {
void* result = g_old_malloc(zone, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -140,7 +140,7 @@
size_t size) {
void* result = g_old_calloc(zone, num_items, size);
if (!result && num_items && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(num_items * size);
return result;
}
@@ -148,7 +148,7 @@
size_t size) {
void* result = g_old_valloc(zone, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -162,7 +162,7 @@
size_t size) {
void* result = g_old_realloc(zone, ptr, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -175,7 +175,7 @@
// http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ).
if (!result && size && alignment >= sizeof(void*) &&
(alignment & (alignment - 1)) == 0) {
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
}
return result;
}
@@ -184,7 +184,7 @@
size_t size) {
void* result = g_old_malloc_purgeable(zone, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -193,7 +193,7 @@
size_t size) {
void* result = g_old_calloc_purgeable(zone, num_items, size);
if (!result && num_items && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(num_items * size);
return result;
}
@@ -201,7 +201,7 @@
size_t size) {
void* result = g_old_valloc_purgeable(zone, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -215,7 +215,7 @@
size_t size) {
void* result = g_old_realloc_purgeable(zone, ptr, size);
if (!result && size)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
return result;
}
@@ -228,7 +228,7 @@
// http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ).
if (!result && size && alignment >= sizeof(void*)
&& (alignment & (alignment - 1)) == 0) {
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(size);
}
return result;
}
@@ -238,7 +238,7 @@
// === C++ operator new ===
void oom_killer_new() {
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(0);
}
#if !defined(ADDRESS_SANITIZER)
@@ -277,7 +277,7 @@
void* info) {
void* result = g_old_cfallocator_system_default(alloc_size, hint, info);
if (!result)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(alloc_size);
return result;
}
@@ -286,7 +286,7 @@
void* info) {
void* result = g_old_cfallocator_malloc(alloc_size, hint, info);
if (!result)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(alloc_size);
return result;
}
@@ -295,7 +295,7 @@
void* info) {
void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info);
if (!result)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(alloc_size);
return result;
}
@@ -310,7 +310,7 @@
{
id result = g_old_allocWithZone(self, _cmd, zone);
if (!result)
- debug::BreakDebugger();
+ TerminateBecauseOutOfMemory(0);
return result;
}
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
index 5904de2..0276b49 100644
--- a/base/process/memory_unittest.cc
+++ b/base/process/memory_unittest.cc
@@ -26,6 +26,7 @@
#endif
#if defined(OS_LINUX)
#include <malloc.h>
+#include "base/test/malloc_wrapper.h"
#endif
#if defined(OS_WIN)
@@ -105,37 +106,6 @@
// test suite setup and does not need to be done again, else mach_override
// will fail.
-#if !defined(ADDRESS_SANITIZER)
-// The following code tests the system implementation of malloc() thus no need
-// to test it under AddressSanitizer.
-TEST(ProcessMemoryTest, MacMallocFailureDoesNotTerminate) {
-#if ARCH_CPU_32_BITS
- // The Mavericks malloc library changed in a way which breaks the tricks used
- // to implement EnableTerminationOnOutOfMemory() with UncheckedMalloc() under
- // 32-bit. Under 64-bit the oom_killer code handles this.
- if (base::mac::IsOSMavericksOrLater())
- return;
-#endif
-
- // Test that ENOMEM doesn't crash via CrMallocErrorBreak two ways: the exit
- // code and lack of the error string. The number of bytes is one less than
- // MALLOC_ABSOLUTE_MAX_SIZE, more than which the system early-returns NULL and
- // does not call through malloc_error_break(). See the comment at
- // EnableTerminationOnOutOfMemory() for more information.
- void* buf = NULL;
- ASSERT_EXIT(
- {
- base::EnableTerminationOnOutOfMemory();
-
- buf = malloc(std::numeric_limits<size_t>::max() - (2 * PAGE_SIZE) - 1);
- },
- testing::KilledBySignal(SIGTRAP),
- "\\*\\*\\* error: can't allocate region.*\\n?.*");
-
- base::debug::Alias(buf);
-}
-#endif // !defined(ADDRESS_SANITIZER)
-
TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
// Assert that freeing an unallocated pointer will crash the process.
char buf[9];
@@ -157,11 +127,12 @@
#endif // defined(OS_MACOSX)
// Android doesn't implement set_new_handler, so we can't use the
-// OutOfMemoryTest cases.
-// OpenBSD does not support these tests either.
+// OutOfMemoryTest cases. OpenBSD does not support these tests either.
+// Don't test these on ASan/TSan/MSan configurations: only test the real
+// allocator.
// TODO(vandebo) make this work on Windows too.
-#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
- !defined(OS_WIN)
+#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) && \
+ !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
#if defined(USE_TCMALLOC)
extern "C" {
@@ -169,6 +140,10 @@
}
#endif // defined(USE_TCMALLOC)
+namespace {
+const char *kOomRegex = "Out of memory";
+} // namespace
+
class OutOfMemoryTest : public testing::Test {
public:
OutOfMemoryTest()
@@ -207,42 +182,42 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = operator new(test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, NewArray) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = new char[test_size_];
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Malloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc(test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Realloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = realloc(NULL, test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Calloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = calloc(1024, test_size_ / 1024L);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, Valloc) {
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = valloc(test_size_);
- }, "");
+ }, kOomRegex);
}
#if defined(OS_LINUX)
@@ -252,7 +227,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = pvalloc(test_size_);
- }, "");
+ }, kOomRegex);
}
#endif // PVALLOC_AVAILABLE == 1
@@ -260,18 +235,16 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = memalign(4, test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
// This tests that the run-time symbol resolution is overriding malloc for
- // shared libraries (including libc itself) as well as for our code.
- std::string format = base::StringPrintf("%%%zud", test_size_);
- char *value = NULL;
+ // shared libraries as well as for our code.
ASSERT_DEATH({
- SetUpInDeathAssert();
- EXPECT_EQ(-1, asprintf(&value, format.c_str(), 0));
- }, "");
+ SetUpInDeathAssert();
+ value_ = MallocWrapper(test_size_);
+ }, kOomRegex);
}
#endif // OS_LINUX
@@ -284,7 +257,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_));
- }, "");
+ }, kOomRegex);
}
#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
@@ -297,7 +270,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc_zone_malloc(zone, test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) {
@@ -305,7 +278,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc_zone_realloc(zone, NULL, test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, CallocPurgeable) {
@@ -313,7 +286,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, VallocPurgeable) {
@@ -321,7 +294,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc_zone_valloc(zone, test_size_);
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) {
@@ -329,7 +302,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
value_ = malloc_zone_memalign(zone, 8, test_size_);
- }, "");
+ }, kOomRegex);
}
// Since these allocation functions take a signed size, it's possible that
@@ -344,7 +317,7 @@
SetUpInDeathAssert();
while ((value_ =
base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {}
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) {
@@ -352,7 +325,7 @@
SetUpInDeathAssert();
while ((value_ =
base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {}
- }, "");
+ }, kOomRegex);
}
TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) {
@@ -360,7 +333,7 @@
SetUpInDeathAssert();
while ((value_ =
base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {}
- }, "");
+ }, kOomRegex);
}
#if !defined(ARCH_CPU_64_BITS)
@@ -372,7 +345,7 @@
ASSERT_DEATH({
SetUpInDeathAssert();
while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {}
- }, "");
+ }, kOomRegex);
}
#endif // !ARCH_CPU_64_BITS
@@ -442,4 +415,5 @@
EXPECT_TRUE(value_ == NULL);
}
#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN)
+#endif // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) &&
+ // !defined(ADDRESS_SANITIZER)
diff --git a/base/process/process.h b/base/process/process.h
index 045f870..808baeb 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -41,7 +41,7 @@
Process(RValue other);
// The destructor does not terminate the process.
- ~Process() {}
+ ~Process();
// Move operator= for C++03 move emulation of this type.
Process& operator=(RValue other);
@@ -91,12 +91,12 @@
// Close the process handle. This will not terminate the process.
void Close();
- // Terminates the process with extreme prejudice. The given |result_code| will
+ // Terminates the process with extreme prejudice. The given |exit_code| will
// be the exit code of the process. If |wait| is true, this method will wait
// for up to one minute for the process to actually terminate.
// Returns true if the process terminates within the allowed time.
- // NOTE: On POSIX |result_code| is ignored.
- bool Terminate(int result_code, bool wait) const;
+ // NOTE: On POSIX |exit_code| is ignored.
+ bool Terminate(int exit_code, bool wait) const;
// Waits for the process to exit. Returns true on success.
// On POSIX, if the process has been signaled then |exit_code| is set to -1.
diff --git a/base/process/process_metrics_ios.cc b/base/process/process_metrics_ios.cc
index 9ae838d..07f2c8d 100644
--- a/base/process/process_metrics_ios.cc
+++ b/base/process/process_metrics_ios.cc
@@ -6,6 +6,8 @@
#include <mach/task.h>
+#include "base/logging.h"
+
namespace base {
namespace {
@@ -30,6 +32,11 @@
return new ProcessMetrics(process);
}
+double ProcessMetrics::GetCPUUsage() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
size_t ProcessMetrics::GetPagefileUsage() const {
task_basic_info_64 task_info_data;
if (!GetTaskInfo(&task_info_data))
@@ -69,4 +76,10 @@
return getpagesize();
}
+// Bytes committed by the system.
+size_t GetSystemCommitCharge() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
} // namespace base
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index dd37236..2d54c4c 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -669,13 +669,13 @@
}
#if defined(OS_CHROMEOS)
- // Report on Chrome OS GEM object graphics memory. /var/run/debugfs_gpu is a
+ // Report on Chrome OS GEM object graphics memory. /run/debugfs_gpu is a
// bind mount into /sys/kernel/debug and synchronously reading the in-memory
// files in /sys is fast.
#if defined(ARCH_CPU_ARM_FAMILY)
- FilePath geminfo_file("/var/run/debugfs_gpu/exynos_gem_objects");
+ FilePath geminfo_file("/run/debugfs_gpu/exynos_gem_objects");
#else
- FilePath geminfo_file("/var/run/debugfs_gpu/i915_gem_objects");
+ FilePath geminfo_file("/run/debugfs_gpu/i915_gem_objects");
#endif
std::string geminfo_data;
meminfo->gem_objects = -1;
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index a083123..a7d16f8 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/kill.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#if defined(OS_MACOSX)
#include <sys/event.h>
@@ -210,6 +211,9 @@
Process::Process(ProcessHandle handle) : process_(handle) {
}
+Process::~Process() {
+}
+
Process::Process(RValue other)
: process_(other.object->process_) {
other.object->Close();
@@ -287,14 +291,59 @@
// end up w/ a zombie when it does finally exit.
}
-bool Process::Terminate(int result_code, bool wait) const {
+#if !defined(OS_NACL_NONSFI)
+bool Process::Terminate(int exit_code, bool wait) const {
// result_code isn't supportable.
DCHECK(IsValid());
- // We don't wait here. It's the responsibility of other code to reap the
- // child.
- // TODO(rvargas) crbug/417532: Move the implementation here.
- return KillProcess(process_, result_code, wait);
+ DCHECK_GT(process_, 1);
+ bool result = kill(process_, SIGTERM) == 0;
+ if (result && wait) {
+ int tries = 60;
+
+ if (RunningOnValgrind()) {
+ // Wait for some extra time when running under Valgrind since the child
+ // processes may take some time doing leak checking.
+ tries *= 2;
+ }
+
+ unsigned sleep_ms = 4;
+
+ // The process may not end immediately due to pending I/O
+ bool exited = false;
+ while (tries-- > 0) {
+ pid_t pid = HANDLE_EINTR(waitpid(process_, NULL, WNOHANG));
+ if (pid == process_) {
+ exited = true;
+ break;
+ }
+ if (pid == -1) {
+ if (errno == ECHILD) {
+ // The wait may fail with ECHILD if another process also waited for
+ // the same pid, causing the process state to get cleaned up.
+ exited = true;
+ break;
+ }
+ DPLOG(ERROR) << "Error waiting for process " << process_;
+ }
+
+ usleep(sleep_ms * 1000);
+ const unsigned kMaxSleepMs = 1000;
+ if (sleep_ms < kMaxSleepMs)
+ sleep_ms *= 2;
+ }
+
+ // If we're waiting and the child hasn't died by now, force it
+ // with a SIGKILL.
+ if (!exited)
+ result = kill(process_, SIGKILL) == 0;
+ }
+
+ if (!result)
+ DPLOG(ERROR) << "Unable to terminate process " << process_;
+
+ return result;
}
+#endif // !defined(OS_NACL_NONSFI)
bool Process::WaitForExit(int* exit_code) {
return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index d72dd49..0d312a3 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -32,6 +32,9 @@
other.object->Close();
}
+Process::~Process() {
+}
+
Process& Process::operator=(RValue other) {
if (this != other.object) {
process_.Set(other.object->process_.Take());
@@ -123,10 +126,17 @@
process_.Close();
}
-bool Process::Terminate(int result_code, bool wait) const {
+bool Process::Terminate(int exit_code, bool wait) const {
DCHECK(IsValid());
- // TODO(rvargas) crbug/417532: Move the implementation here.
- return KillProcess(Handle(), result_code, wait);
+ bool result = (::TerminateProcess(Handle(), exit_code) != FALSE);
+ if (result && wait) {
+ // The process may not end immediately due to pending I/O
+ if (::WaitForSingleObject(Handle(), 60 * 1000) != WAIT_OBJECT_0)
+ DPLOG(ERROR) << "Error waiting for process exit";
+ } else if (!result) {
+ DPLOG(ERROR) << "Unable to terminate process";
+ }
+ return result;
}
bool Process::WaitForExit(int* exit_code) {
diff --git a/base/profiler/native_stack_sampler.cc b/base/profiler/native_stack_sampler.cc
new file mode 100644
index 0000000..8b4731b
--- /dev/null
+++ b/base/profiler/native_stack_sampler.cc
@@ -0,0 +1,13 @@
+// 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/profiler/native_stack_sampler.h"
+
+namespace base {
+
+NativeStackSampler::NativeStackSampler() {}
+
+NativeStackSampler::~NativeStackSampler() {}
+
+} // namespace base
diff --git a/base/profiler/native_stack_sampler.h b/base/profiler/native_stack_sampler.h
new file mode 100644
index 0000000..bc170dc
--- /dev/null
+++ b/base/profiler/native_stack_sampler.h
@@ -0,0 +1,50 @@
+// 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 BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+#define BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/profiler/stack_sampling_profiler.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+// NativeStackSampler is an implementation detail of StackSamplingProfiler. It
+// abstracts the native implementation required to record a stack sample for a
+// given thread.
+class NativeStackSampler {
+ public:
+ virtual ~NativeStackSampler();
+
+ // Creates a stack sampler that records samples for |thread_handle|. Returns
+ // null if this platform does not support stack sampling.
+ static scoped_ptr<NativeStackSampler> Create(PlatformThreadId thread_id);
+
+ // The following functions are all called on the SamplingThread (not the
+ // thread being sampled).
+
+ // Notifies the sampler that we're starting to record a new profile. Modules
+ // shared across samples in the profile should be recorded in |modules|.
+ virtual void ProfileRecordingStarting(
+ std::vector<StackSamplingProfiler::Module>* modules) = 0;
+
+ // Records a stack sample to |sample|.
+ virtual void RecordStackSample(StackSamplingProfiler::Sample* sample) = 0;
+
+ // Notifies the sampler that we've stopped recording the current
+ // profile.
+ virtual void ProfileRecordingStopped() = 0;
+
+ protected:
+ NativeStackSampler();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NativeStackSampler);
+};
+
+} // namespace base
+
+#endif // BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+
diff --git a/base/profiler/scoped_profile.h b/base/profiler/scoped_profile.h
index c1e2830..6b0c800 100644
--- a/base/profiler/scoped_profile.h
+++ b/base/profiler/scoped_profile.h
@@ -30,6 +30,14 @@
FROM_HERE_WITH_EXPLICIT_FUNCTION(#dispatch_function_name), \
::tracked_objects::ScopedProfile::ENABLED)
+// Same as TRACK_RUN_IN_THIS_SCOPED_REGION except that there's an extra param
+// which is concatenated with the function name for better filtering.
+#define TRACK_SCOPED_REGION(category_name, dispatch_function_name) \
+ ::tracked_objects::ScopedProfile LINE_BASED_VARIABLE_NAME_FOR_PROFILING( \
+ FROM_HERE_WITH_EXPLICIT_FUNCTION( \
+ "[" category_name "]" dispatch_function_name), \
+ ::tracked_objects::ScopedProfile::ENABLED)
+
namespace tracked_objects {
class Births;
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index 57b7b35..9da6628 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -9,114 +9,144 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/singleton.h"
+#include "base/profiler/native_stack_sampler.h"
#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
#include "base/timer/elapsed_timer.h"
-template <typename T> struct DefaultSingletonTraits;
-
namespace base {
+// DefaultProfileProcessor ----------------------------------------------------
+
namespace {
-// Thread-safe singleton class that stores collected profiles waiting to be
-// processed.
-class PendingProfiles {
+// Singleton class responsible for providing the default processing for profiles
+// (i.e. for profiles generated by profilers without their own completed
+// callback).
+class DefaultProfileProcessor {
public:
- PendingProfiles();
- ~PendingProfiles();
+ using CompletedCallback = StackSamplingProfiler::CompletedCallback;
- static PendingProfiles* GetInstance();
+ ~DefaultProfileProcessor();
- // Appends |profiles|. This function is thread safe.
- void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles);
- // Gets the pending profiles into *|profiles|. This function is thread safe.
- void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles);
+ static DefaultProfileProcessor* GetInstance();
+
+ // Sets the callback to use for processing profiles captured without a
+ // per-profiler completed callback. Pending completed profiles are stored in
+ // this object until a non-null callback is provided here. This function is
+ // thread-safe.
+ void SetCompletedCallback(CompletedCallback callback);
+
+ // Processes |profiles|. This function is thread safe.
+ void ProcessProfiles(
+ const StackSamplingProfiler::CallStackProfiles& profiles);
private:
- Lock profiles_lock_;
- std::vector<StackSamplingProfiler::Profile> profiles_;
+ friend struct DefaultSingletonTraits<DefaultProfileProcessor>;
- DISALLOW_COPY_AND_ASSIGN(PendingProfiles);
+ DefaultProfileProcessor();
+
+ // Copies the pending profiles from |profiles_| into |profiles|, and clears
+ // |profiles_|. This function may be called on any thread.
+ void GetAndClearPendingProfiles(
+ StackSamplingProfiler::CallStackProfiles* profiles);
+
+ // Gets the current completed callback, with proper locking.
+ CompletedCallback GetCompletedCallback() const;
+
+ mutable Lock callback_lock_;
+ CompletedCallback default_completed_callback_;
+
+ Lock profiles_lock_;
+ StackSamplingProfiler::CallStackProfiles profiles_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor);
};
-PendingProfiles::PendingProfiles() {}
-
-PendingProfiles::~PendingProfiles() {}
+DefaultProfileProcessor::~DefaultProfileProcessor() {}
// static
-PendingProfiles* PendingProfiles::GetInstance() {
- return Singleton<PendingProfiles>::get();
+DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() {
+ return Singleton<DefaultProfileProcessor>::get();
}
-void PendingProfiles::PutProfiles(
- const std::vector<StackSamplingProfiler::Profile>& profiles) {
- AutoLock scoped_lock(profiles_lock_);
- profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) {
+ {
+ AutoLock scoped_lock(callback_lock_);
+ default_completed_callback_ = callback;
+ }
+
+ if (!callback.is_null()) {
+ // Provide any pending profiles to the callback immediately.
+ StackSamplingProfiler::CallStackProfiles profiles;
+ GetAndClearPendingProfiles(&profiles);
+ if (!profiles.empty())
+ callback.Run(profiles);
+ }
}
-void PendingProfiles::GetProfiles(
- std::vector<StackSamplingProfiler::Profile>* profiles) {
+void DefaultProfileProcessor::ProcessProfiles(
+ const StackSamplingProfiler::CallStackProfiles& profiles) {
+ CompletedCallback callback = GetCompletedCallback();
+
+ // Store pending profiles if we don't have a valid callback.
+ if (!callback.is_null()) {
+ callback.Run(profiles);
+ } else {
+ AutoLock scoped_lock(profiles_lock_);
+ profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+ }
+}
+
+DefaultProfileProcessor::DefaultProfileProcessor() {}
+
+void DefaultProfileProcessor::GetAndClearPendingProfiles(
+ StackSamplingProfiler::CallStackProfiles* profiles) {
profiles->clear();
AutoLock scoped_lock(profiles_lock_);
profiles_.swap(*profiles);
}
+
+DefaultProfileProcessor::CompletedCallback
+DefaultProfileProcessor::GetCompletedCallback() const {
+ AutoLock scoped_lock(callback_lock_);
+ return default_completed_callback_;
+}
+
} // namespace
+// StackSamplingProfiler::Module ----------------------------------------------
+
StackSamplingProfiler::Module::Module() : base_address(nullptr) {}
+StackSamplingProfiler::Module::Module(const void* base_address,
+ const std::string& id,
+ const FilePath& filename)
+ : base_address(base_address), id(id), filename(filename) {}
StackSamplingProfiler::Module::~Module() {}
-StackSamplingProfiler::Frame::Frame()
- : instruction_pointer(nullptr),
- module_index(-1) {}
+// StackSamplingProfiler::Frame -----------------------------------------------
+
+StackSamplingProfiler::Frame::Frame(const void* instruction_pointer,
+ size_t module_index)
+ : instruction_pointer(instruction_pointer),
+ module_index(module_index) {}
StackSamplingProfiler::Frame::~Frame() {}
-StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {}
+// StackSamplingProfiler::CallStackProfile ------------------------------------
-StackSamplingProfiler::Profile::~Profile() {}
+StackSamplingProfiler::CallStackProfile::CallStackProfile()
+ : preserve_sample_ordering(false), user_data(0) {}
-class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
- public:
- // Samples stacks using |native_sampler|. When complete, invokes
- // |profiles_callback| with the collected profiles. |profiles_callback| must
- // be thread-safe and may consume the contents of the vector.
- SamplingThread(
- scoped_ptr<NativeStackSampler> native_sampler,
- const SamplingParams& params,
- Callback<void(const std::vector<Profile>&)> completed_callback);
- ~SamplingThread() override;
+StackSamplingProfiler::CallStackProfile::~CallStackProfile() {}
- // Implementation of PlatformThread::Delegate:
- void ThreadMain() override;
-
- void Stop();
-
- private:
- // Collects a profile from a single burst. Returns true if the profile was
- // collected, or false if collection was stopped before it completed.
- bool CollectProfile(Profile* profile, TimeDelta* elapsed_time);
- // Collects profiles from all bursts, or until the sampling is stopped. If
- // stopped before complete, |profiles| will contains only full bursts.
- void CollectProfiles(std::vector<Profile>* profiles);
-
- scoped_ptr<NativeStackSampler> native_sampler_;
-
- const SamplingParams params_;
-
- WaitableEvent stop_event_;
-
- Callback<void(const std::vector<Profile>&)> completed_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(SamplingThread);
-};
+// StackSamplingProfiler::SamplingThread --------------------------------------
StackSamplingProfiler::SamplingThread::SamplingThread(
scoped_ptr<NativeStackSampler> native_sampler,
const SamplingParams& params,
- Callback<void(const std::vector<Profile>&)> completed_callback)
+ CompletedCallback completed_callback)
: native_sampler_(native_sampler.Pass()),
params_(params),
stop_event_(false, false),
@@ -128,61 +158,79 @@
void StackSamplingProfiler::SamplingThread::ThreadMain() {
PlatformThread::SetName("Chrome_SamplingProfilerThread");
- std::vector<Profile> profiles;
+ CallStackProfiles profiles;
CollectProfiles(&profiles);
completed_callback_.Run(profiles);
}
+// Depending on how long the sampling takes and the length of the sampling
+// interval, a burst of samples could take arbitrarily longer than
+// samples_per_burst * sampling_interval. In this case, we (somewhat
+// arbitrarily) honor the number of samples requested rather than strictly
+// adhering to the sampling intervals. Once we have established users for the
+// StackSamplingProfiler and the collected data to judge, we may go the other
+// way or make this behavior configurable.
bool StackSamplingProfiler::SamplingThread::CollectProfile(
- Profile* profile,
+ CallStackProfile* profile,
TimeDelta* elapsed_time) {
ElapsedTimer profile_timer;
- Profile current_profile;
- native_sampler_->ProfileRecordingStarting(¤t_profile);
+ CallStackProfile current_profile;
+ native_sampler_->ProfileRecordingStarting(¤t_profile.modules);
current_profile.sampling_period = params_.sampling_interval;
- bool stopped_early = false;
+ bool burst_completed = true;
+ TimeDelta previous_elapsed_sample_time;
for (int i = 0; i < params_.samples_per_burst; ++i) {
- ElapsedTimer sample_timer;
- current_profile.samples.push_back(Sample());
- native_sampler_->RecordStackSample(¤t_profile.samples.back());
- TimeDelta elapsed_sample_time = sample_timer.Elapsed();
- if (i != params_.samples_per_burst - 1) {
+ if (i != 0) {
+ // Always wait, even if for 0 seconds, so we can observe a signal on
+ // stop_event_.
if (stop_event_.TimedWait(
- std::max(params_.sampling_interval - elapsed_sample_time,
+ std::max(params_.sampling_interval - previous_elapsed_sample_time,
TimeDelta()))) {
- stopped_early = true;
+ burst_completed = false;
break;
}
}
+ ElapsedTimer sample_timer;
+ current_profile.samples.push_back(Sample());
+ native_sampler_->RecordStackSample(¤t_profile.samples.back());
+ previous_elapsed_sample_time = sample_timer.Elapsed();
}
*elapsed_time = profile_timer.Elapsed();
current_profile.profile_duration = *elapsed_time;
+ current_profile.preserve_sample_ordering = params_.preserve_sample_ordering;
+ current_profile.user_data = params_.user_data;
native_sampler_->ProfileRecordingStopped();
- if (!stopped_early)
+ if (burst_completed)
*profile = current_profile;
- return !stopped_early;
+ return burst_completed;
}
+// In an analogous manner to CollectProfile() and samples exceeding the expected
+// total sampling time, bursts may also exceed the burst_interval. We adopt the
+// same wait-and-see approach here.
void StackSamplingProfiler::SamplingThread::CollectProfiles(
- std::vector<Profile>* profiles) {
+ CallStackProfiles* profiles) {
if (stop_event_.TimedWait(params_.initial_delay))
return;
+ TimeDelta previous_elapsed_profile_time;
for (int i = 0; i < params_.bursts; ++i) {
- Profile profile;
- TimeDelta elapsed_profile_time;
- if (CollectProfile(&profile, &elapsed_profile_time))
- profiles->push_back(profile);
- else
- return;
+ if (i != 0) {
+ // Always wait, even if for 0 seconds, so we can observe a signal on
+ // stop_event_.
+ if (stop_event_.TimedWait(
+ std::max(params_.burst_interval - previous_elapsed_profile_time,
+ TimeDelta())))
+ return;
+ }
- if (stop_event_.TimedWait(
- std::max(params_.burst_interval - elapsed_profile_time,
- TimeDelta())))
+ CallStackProfile profile;
+ if (!CollectProfile(&profile, &previous_elapsed_profile_time))
return;
+ profiles->push_back(profile);
}
}
@@ -190,14 +238,7 @@
stop_event_.Signal();
}
-void StackSamplingProfiler::SamplingThreadDeleter::operator()(
- SamplingThread* thread) const {
- delete thread;
-}
-
-StackSamplingProfiler::NativeStackSampler::NativeStackSampler() {}
-
-StackSamplingProfiler::NativeStackSampler::~NativeStackSampler() {}
+// StackSamplingProfiler ------------------------------------------------------
StackSamplingProfiler::SamplingParams::SamplingParams()
: initial_delay(TimeDelta::FromMilliseconds(0)),
@@ -205,29 +246,40 @@
burst_interval(TimeDelta::FromMilliseconds(10000)),
samples_per_burst(300),
sampling_interval(TimeDelta::FromMilliseconds(100)),
- preserve_sample_ordering(false) {
+ preserve_sample_ordering(false),
+ user_data(0) {
}
StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
const SamplingParams& params)
: thread_id_(thread_id), params_(params) {}
-StackSamplingProfiler::~StackSamplingProfiler() {}
+StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
+ const SamplingParams& params,
+ CompletedCallback callback)
+ : thread_id_(thread_id), params_(params), completed_callback_(callback) {}
+
+StackSamplingProfiler::~StackSamplingProfiler() {
+ Stop();
+ if (!sampling_thread_handle_.is_null())
+ PlatformThread::Join(sampling_thread_handle_);
+}
void StackSamplingProfiler::Start() {
- native_sampler_ = NativeStackSampler::Create(thread_id_);
- if (!native_sampler_)
+ scoped_ptr<NativeStackSampler> native_sampler =
+ NativeStackSampler::Create(thread_id_);
+ if (!native_sampler)
return;
+ CompletedCallback callback =
+ !completed_callback_.is_null() ? completed_callback_ :
+ Bind(&DefaultProfileProcessor::ProcessProfiles,
+ Unretained(DefaultProfileProcessor::GetInstance()));
sampling_thread_.reset(
- new SamplingThread(
- native_sampler_.Pass(), params_,
- (custom_completed_callback_.is_null() ?
- Bind(&PendingProfiles::PutProfiles,
- Unretained(PendingProfiles::GetInstance())) :
- custom_completed_callback_)));
- if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get()))
- LOG(ERROR) << "failed to create thread";
+ new SamplingThread(native_sampler.Pass(), params_, callback));
+ if (!PlatformThread::Create(0, sampling_thread_.get(),
+ &sampling_thread_handle_))
+ sampling_thread_.reset();
}
void StackSamplingProfiler::Stop() {
@@ -236,14 +288,12 @@
}
// static
-void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) {
- PendingProfiles::GetInstance()->GetProfiles(profiles);
+void StackSamplingProfiler::SetDefaultCompletedCallback(
+ CompletedCallback callback) {
+ DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback);
}
-void StackSamplingProfiler::SetCustomCompletedCallback(
- Callback<void(const std::vector<Profile>&)> callback) {
- custom_completed_callback_ = callback;
-}
+// StackSamplingProfiler::Frame global functions ------------------------------
bool operator==(const StackSamplingProfiler::Frame &a,
const StackSamplingProfiler::Frame &b) {
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
index 8d7671e..9d52f27 100644
--- a/base/profiler/stack_sampling_profiler.h
+++ b/base/profiler/stack_sampling_profiler.h
@@ -13,17 +13,20 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
+#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
namespace base {
+class NativeStackSampler;
+
// StackSamplingProfiler periodically stops a thread to sample its stack, for
// the purpose of collecting information about which code paths are
// executing. This information is used in aggregate by UMA to identify hot
// and/or janky code paths.
//
-// Sample StackStackSamplingProfiler usage:
+// Sample StackSamplingProfiler usage:
//
// // Create and customize params as desired.
// base::StackStackSamplingProfiler::SamplingParams params;
@@ -31,32 +34,47 @@
// base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
// params);
//
-// // To process the profiles within Chrome rather than via UMA, set a custom
-// // completed callback:
-// base::Callback<void(const std::vector<Profile>&)>
+// // Or, to process the profiles within Chrome rather than via UMA, use a
+// // custom completed callback:
+// base::StackStackSamplingProfiler::CompletedCallback
// thread_safe_callback = ...;
-// profiler.SetCustomCompletedCallback(thread_safe_callback);
+// base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
+// params, thread_safe_callback);
//
// profiler.Start();
// // ... work being done on the target thread here ...
// profiler.Stop(); // optional, stops collection before complete per params
//
-// When all profiles are complete or the profiler is stopped, if the custom
-// completed callback was set it will be called from the profiler thread with
-// the completed profiles. If no callback was set, the profiles are stored
-// internally and retrieved for UMA through
-// GetPendingProfiles(). GetPendingProfiles() should never be called by other
-// code; to retrieve profiles for in-process processing, set a completed
-// callback.
+// The default SamplingParams causes stacks to be recorded in a single burst at
+// a 10Hz interval for a total of 30 seconds. All of these parameters may be
+// altered as desired.
+//
+// When all call stack profiles are complete or the profiler is stopped, if the
+// custom completed callback was set it is called from a thread created by the
+// profiler with the completed profiles. A profile is considered complete if all
+// requested samples were recorded for the profile (i.e. it was not stopped
+// prematurely). If no callback was set, the default completed callback will be
+// called with the profiles. It is expected that the the default completed
+// callback is set by the metrics system to allow profiles to be provided via
+// UMA.
+//
+// The results of the profiling are passed to the completed callback and consist
+// of a vector of CallStackProfiles. Each CallStackProfile corresponds to a
+// burst as specified in SamplingParams and contains a set of Samples and
+// Modules. One Sample corresponds to a single recorded stack, and the Modules
+// record those modules associated with the recorded stack frames.
class BASE_EXPORT StackSamplingProfiler {
public:
// Module represents the module (DLL or exe) corresponding to a stack frame.
struct BASE_EXPORT Module {
Module();
+ Module(const void* base_address, const std::string& id,
+ const FilePath& filename);
~Module();
// Points to the base address of the module.
const void* base_address;
+
// An opaque binary string that uniquely identifies a particular program
// version with high probability. This is parsed from headers of the loaded
// module.
@@ -65,68 +83,53 @@
// On Windows:
// GUID + AGE in the debug image headers of a module.
std::string id;
+
// The filename of the module.
FilePath filename;
};
// Frame represents an individual sampled stack frame with module information.
struct BASE_EXPORT Frame {
- Frame();
+ // Identifies an unknown module.
+ static const size_t kUnknownModuleIndex = static_cast<size_t>(-1);
+
+ Frame(const void* instruction_pointer, size_t module_index);
~Frame();
// The sampled instruction pointer within the function.
const void* instruction_pointer;
- // Index of the module in the array of modules. We don't represent module
- // state directly here to save space.
- int module_index;
+
+ // Index of the module in CallStackProfile::modules. We don't represent
+ // module state directly here to save space.
+ size_t module_index;
};
// Sample represents a set of stack frames.
using Sample = std::vector<Frame>;
- // Profile represents a set of samples.
- struct BASE_EXPORT Profile {
- Profile();
- ~Profile();
+ // CallStackProfile represents a set of samples.
+ struct BASE_EXPORT CallStackProfile {
+ CallStackProfile();
+ ~CallStackProfile();
std::vector<Module> modules;
std::vector<Sample> samples;
+
// Duration of this profile.
TimeDelta profile_duration;
+
// Time between samples.
TimeDelta sampling_period;
+
// True if sample ordering is important and should be preserved if and when
// this profile is compressed and processed.
bool preserve_sample_ordering;
+
+ // User data associated with this profile.
+ uintptr_t user_data;
};
- // NativeStackSampler abstracts the native implementation required to record a
- // stack sample for a given thread.
- class NativeStackSampler {
- public:
- virtual ~NativeStackSampler();
-
- // Create a stack sampler that records samples for |thread_handle|. Returns
- // null if this platform does not support stack sampling.
- static scoped_ptr<NativeStackSampler> Create(PlatformThreadId thread_id);
-
- // Notify the sampler that we're starting to record a new profile. This
- // function is called on the SamplingThread.
- virtual void ProfileRecordingStarting(Profile* profile) = 0;
-
- // Record a stack sample. This function is called on the SamplingThread.
- virtual void RecordStackSample(Sample* sample) = 0;
-
- // Notify the sampler that we've stopped recording the current profile. This
- // function is called on the SamplingThread.
- virtual void ProfileRecordingStopped() = 0;
-
- protected:
- NativeStackSampler();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NativeStackSampler);
- };
+ using CallStackProfiles = std::vector<CallStackProfile>;
// Represents parameters that configure the sampling.
struct BASE_EXPORT SamplingParams {
@@ -134,51 +137,106 @@
// Time to delay before first samples are taken. Defaults to 0.
TimeDelta initial_delay;
+
// Number of sampling bursts to perform. Defaults to 1.
int bursts;
+
// Interval between sampling bursts. This is the desired duration from the
// start of one burst to the start of the next burst. Defaults to 10s.
TimeDelta burst_interval;
+
// Number of samples to record per burst. Defaults to 300.
int samples_per_burst;
+
// Interval between samples during a sampling burst. This is the desired
- // duration from the start of one burst to the start of the next
- // burst. Defaults to 100ms.
+ // duration from the start of one sample to the start of the next
+ // sample. Defaults to 100ms.
TimeDelta sampling_interval;
+
// True if sample ordering is important and should be preserved if and when
// this profile is compressed and processed. Defaults to false.
bool preserve_sample_ordering;
+
+ // User data associated with this profile.
+ uintptr_t user_data;
};
+ // The callback type used to collect completed profiles.
+ //
+ // IMPORTANT NOTE: the callback is invoked on a thread the profiler
+ // constructs, rather than on the thread used to construct the profiler and
+ // set the callback, and thus the callback must be callable on any thread. For
+ // threads with message loops that create StackSamplingProfilers, posting a
+ // task to the message loop with a copy of the profiles is the recommended
+ // thread-safe callback implementation.
+ using CompletedCallback = Callback<void(const CallStackProfiles&)>;
+
+ // Creates a profiler that sends completed profiles to the default completed
+ // callback.
StackSamplingProfiler(PlatformThreadId thread_id,
const SamplingParams& params);
+ // Creates a profiler that sends completed profiles to |completed_callback|.
+ StackSamplingProfiler(PlatformThreadId thread_id,
+ const SamplingParams& params,
+ CompletedCallback callback);
~StackSamplingProfiler();
// Initializes the profiler and starts sampling.
void Start();
+
// Stops the profiler and any ongoing sampling. Calling this function is
- // optional; if not invoked profiling will terminate when all the profiling
- // bursts specified in the SamplingParams are completed.
+ // optional; if not invoked profiling terminates when all the profiling bursts
+ // specified in the SamplingParams are completed.
void Stop();
- // Gets the pending profiles into *|profiles| and clears the internal
- // storage. This function is thread safe.
+ // Sets a callback to process profiles collected by profiler instances without
+ // a completed callback. Profiles are queued internally until a non-null
+ // callback is provided to this function,
//
- // ***This is intended for use only by UMA.*** Callers who want to process the
- // collected profiles should use SetCustomCompletedCallback.
- static void GetPendingProfiles(std::vector<Profile>* profiles);
-
- // By default, collected profiles are stored internally and can be retrieved
- // by GetPendingProfiles. If a callback is provided via this function,
- // however, it will be called with the collected profiles instead. Note that
- // this call to the callback occurs *on the profiler thread*.
- void SetCustomCompletedCallback(
- Callback<void(const std::vector<Profile>&)> callback);
+ // The callback is typically called on a thread created by the profiler. If
+ // completed profiles are queued when set, however, it will also be called
+ // immediately on the calling thread.
+ static void SetDefaultCompletedCallback(CompletedCallback callback);
private:
- class SamplingThread;
- struct SamplingThreadDeleter {
- void operator() (SamplingThread* thread) const;
+ // SamplingThread is a separate thread used to suspend and sample stacks from
+ // the target thread.
+ class SamplingThread : public PlatformThread::Delegate {
+ public:
+ // Samples stacks using |native_sampler|. When complete, invokes
+ // |completed_callback| with the collected call stack profiles.
+ // |completed_callback| must be callable on any thread.
+ SamplingThread(scoped_ptr<NativeStackSampler> native_sampler,
+ const SamplingParams& params,
+ CompletedCallback completed_callback);
+ ~SamplingThread() override;
+
+ // PlatformThread::Delegate:
+ void ThreadMain() override;
+
+ void Stop();
+
+ private:
+ // Collects a call stack profile from a single burst. Returns true if the
+ // profile was collected, or false if collection was stopped before it
+ // completed.
+ bool CollectProfile(CallStackProfile* profile, TimeDelta* elapsed_time);
+
+ // Collects call stack profiles from all bursts, or until the sampling is
+ // stopped. If stopped before complete, |call_stack_profiles| will contain
+ // only full bursts.
+ void CollectProfiles(CallStackProfiles* profiles);
+
+ scoped_ptr<NativeStackSampler> native_sampler_;
+ const SamplingParams params_;
+
+ // If Stop() is called, it signals this event to force the sampling to
+ // terminate before all the samples specified in |params_| are collected.
+ WaitableEvent stop_event_;
+
+ const CompletedCallback completed_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SamplingThread);
};
// The thread whose stack will be sampled.
@@ -186,18 +244,18 @@
const SamplingParams params_;
- scoped_ptr<SamplingThread, SamplingThreadDeleter> sampling_thread_;
- scoped_ptr<NativeStackSampler> native_sampler_;
+ scoped_ptr<SamplingThread> sampling_thread_;
+ PlatformThreadHandle sampling_thread_handle_;
- Callback<void(const std::vector<Profile>&)> custom_completed_callback_;
+ const CompletedCallback completed_callback_;
DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler);
};
-// Defined to allow equality check of Samples.
+// The metrics provider code wants to put Samples in a map and compare them,
+// which requires us to define a few operators.
BASE_EXPORT bool operator==(const StackSamplingProfiler::Frame& a,
const StackSamplingProfiler::Frame& b);
-// Defined to allow ordering of Samples.
BASE_EXPORT bool operator<(const StackSamplingProfiler::Frame& a,
const StackSamplingProfiler::Frame& b);
diff --git a/base/profiler/stack_sampling_profiler_posix.cc b/base/profiler/stack_sampling_profiler_posix.cc
index 6a44d7e..bce37e1 100644
--- a/base/profiler/stack_sampling_profiler_posix.cc
+++ b/base/profiler/stack_sampling_profiler_posix.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/profiler/stack_sampling_profiler.h"
+#include "base/profiler/native_stack_sampler.h"
namespace base {
-scoped_ptr<StackSamplingProfiler::NativeStackSampler>
-StackSamplingProfiler::NativeStackSampler::Create(PlatformThreadId thread_id) {
+scoped_ptr<NativeStackSampler> NativeStackSampler::Create(
+ PlatformThreadId thread_id) {
return scoped_ptr<NativeStackSampler>();
}
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
index ad9e926..5ade15a 100644
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <sstream>
-
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/path_service.h"
#include "base/profiler/stack_sampling_profiler.h"
+#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
@@ -15,30 +14,37 @@
namespace base {
+using SamplingParams = StackSamplingProfiler::SamplingParams;
using Frame = StackSamplingProfiler::Frame;
using Module = StackSamplingProfiler::Module;
using Sample = StackSamplingProfiler::Sample;
-using Profile = StackSamplingProfiler::Profile;
+using CallStackProfile = StackSamplingProfiler::CallStackProfile;
+using CallStackProfiles = StackSamplingProfiler::CallStackProfiles;
namespace {
+
// A thread to target for profiling, whose stack is guaranteed to contain
// SignalAndWaitUntilSignaled() when coordinated with the main thread.
class TargetThread : public PlatformThread::Delegate {
public:
TargetThread();
- // Implementation of PlatformThread::Delegate:
+ // PlatformThread::Delegate:
void ThreadMain() override;
- // Wait for the thread to have started and be executing in
+ // Waits for the thread to have started and be executing in
// SignalAndWaitUntilSignaled().
void WaitForThreadStart();
- // Allow the thread to return from SignalAndWaitUntilSignaled() and finish
+
+ // Allows the thread to return from SignalAndWaitUntilSignaled() and finish
// execution.
void SignalThreadToFinish();
// This function is guaranteed to be executing between calls to
- // WaitForThreadStart() and SignalThreadToFinish().
+ // WaitForThreadStart() and SignalThreadToFinish(). This function is static so
+ // that we can get a straightforward address for it in one of the tests below,
+ // rather than dealing with the complexity of a member function pointer
+ // representation.
static void SignalAndWaitUntilSignaled(WaitableEvent* thread_started_event,
WaitableEvent* finish_event);
@@ -81,49 +87,105 @@
ALLOW_UNUSED_LOCAL(x);
}
+// Called on the profiler thread when complete, to collect profiles.
+void SaveProfiles(CallStackProfiles* profiles,
+ const CallStackProfiles& pending_profiles) {
+ *profiles = pending_profiles;
+}
+
// Called on the profiler thread when complete. Collects profiles produced by
// the profiler, and signals an event to allow the main thread to know that that
// the profiler is done.
-void SaveProfilesAndSignalEvent(std::vector<Profile>* profiles,
+void SaveProfilesAndSignalEvent(CallStackProfiles* profiles,
WaitableEvent* event,
- const std::vector<Profile>& pending_profiles) {
+ const CallStackProfiles& pending_profiles) {
*profiles = pending_profiles;
event->Signal();
}
-// Captures profiles as specified by |params| on the TargetThread, and returns
-// them in |profiles|. Waits up to |profiler_wait_time| for the profiler to
-// complete.
-void CaptureProfiles(const StackSamplingProfiler::SamplingParams& params,
- std::vector<Profile>* profiles,
- TimeDelta profiler_wait_time) {
+// Executes the function with the target thread running and executing within
+// SignalAndWaitUntilSignaled(). Performs all necessary target thread startup
+// and shutdown work before and afterward.
+template <class Function>
+void WithTargetThread(Function function) {
TargetThread target_thread;
PlatformThreadHandle target_thread_handle;
EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
target_thread.WaitForThreadStart();
- WaitableEvent sampling_thread_completed(true, false);
- profiles->clear();
- StackSamplingProfiler profiler(target_thread.id(), params);
- profiler.SetCustomCompletedCallback(
- Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
- Unretained(&sampling_thread_completed)));
- profiler.Start();
- sampling_thread_completed.TimedWait(profiler_wait_time);
- profiler.Stop();
- sampling_thread_completed.Wait();
+ function(target_thread.id());
target_thread.SignalThreadToFinish();
PlatformThread::Join(target_thread_handle);
}
+// Captures profiles as specified by |params| on the TargetThread, and returns
+// them in |profiles|. Waits up to |profiler_wait_time| for the profiler to
+// complete.
+void CaptureProfilesWithObjectCallback(const SamplingParams& params,
+ CallStackProfiles* profiles,
+ TimeDelta profiler_wait_time) {
+ profiles->clear();
+
+ WithTargetThread([¶ms, profiles, profiler_wait_time](
+ PlatformThreadId target_thread_id) {
+ WaitableEvent sampling_thread_completed(true, false);
+ const StackSamplingProfiler::CompletedCallback callback =
+ Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
+ Unretained(&sampling_thread_completed));
+ StackSamplingProfiler profiler(target_thread_id, params, callback);
+ profiler.Start();
+ sampling_thread_completed.TimedWait(profiler_wait_time);
+ profiler.Stop();
+ sampling_thread_completed.Wait();
+ });
+}
+
+// Captures profiles as specified by |params| on the TargetThread, and returns
+// them in |profiles|. Uses the default callback rather than a per-object
+// callback.
+void CaptureProfilesWithDefaultCallback(const SamplingParams& params,
+ CallStackProfiles* profiles) {
+ profiles->clear();
+
+ WithTargetThread([¶ms, profiles](PlatformThreadId target_thread_id) {
+ WaitableEvent sampling_thread_completed(false, false);
+ StackSamplingProfiler::SetDefaultCompletedCallback(
+ Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
+ Unretained(&sampling_thread_completed)));
+
+ StackSamplingProfiler profiler(target_thread_id, params);
+ profiler.Start();
+ sampling_thread_completed.Wait();
+
+ StackSamplingProfiler::SetDefaultCompletedCallback(
+ StackSamplingProfiler::CompletedCallback());
+ });
+}
+
+// Runs the profiler with |params| on the TargetThread, with no default or
+// per-object callback.
+void RunProfilerWithNoCallback(const SamplingParams& params,
+ TimeDelta profiler_wait_time) {
+ WithTargetThread([¶ms, profiler_wait_time](
+ PlatformThreadId target_thread_id) {
+ StackSamplingProfiler profiler(target_thread_id, params);
+ profiler.Start();
+ // Since we don't specify a callback, we don't have a synchronization
+ // mechanism with the sampling thread. Just sleep instead.
+ PlatformThread::Sleep(profiler_wait_time);
+ profiler.Stop();
+ });
+}
+
// If this executable was linked with /INCREMENTAL (the default for non-official
// debug and release builds on Windows), function addresses do not correspond to
// function code itself, but instead to instructions in the Incremental Link
-// Table that jump to the functions. Check for a jump instruction and if present
-// do a little decompilation to find the function's actual starting address.
+// Table that jump to the functions. Checks for a jump instruction and if
+// present does a little decompilation to find the function's actual starting
+// address.
const void* MaybeFixupFunctionAddressForILT(const void* function_address) {
#if defined(_WIN64)
const unsigned char* opcode =
@@ -131,10 +193,10 @@
if (*opcode == 0xe9) {
// This is a relative jump instruction. Assume we're in the ILT and compute
// the function start address from the instruction offset.
- const unsigned char* offset = opcode + 1;
- const unsigned char* next_instruction = opcode + 5;
- return next_instruction +
- static_cast<int64>(*reinterpret_cast<const int32*>(offset));
+ const int32* offset = reinterpret_cast<const int32*>(opcode + 1);
+ const unsigned char* next_instruction =
+ reinterpret_cast<const unsigned char*>(offset + 1);
+ return next_instruction + *offset;
}
#endif
return function_address;
@@ -150,11 +212,9 @@
int function_size) {
function_address = MaybeFixupFunctionAddressForILT(function_address);
for (auto it = sample.begin(); it != sample.end(); ++it) {
- if ((reinterpret_cast<const unsigned char*>(it->instruction_pointer) >=
- reinterpret_cast<const unsigned char*>(function_address)) &&
- (reinterpret_cast<const unsigned char*>(it->instruction_pointer) <
- (reinterpret_cast<const unsigned char*>(function_address) +
- function_size)))
+ if ((it->instruction_pointer >= function_address) &&
+ (it->instruction_pointer <
+ (static_cast<const unsigned char*>(function_address) + function_size)))
return it;
}
return sample.end();
@@ -164,56 +224,60 @@
std::string FormatSampleForDiagnosticOutput(
const Sample& sample,
const std::vector<Module>& modules) {
- std::ostringstream stream;
+ std::string output;
for (const Frame& frame: sample) {
- stream << frame.instruction_pointer << " "
- << modules[frame.module_index].filename.value() << std::endl;
+ output += StringPrintf(
+ "0x%p %s\n", frame.instruction_pointer,
+ modules[frame.module_index].filename.AsUTF8Unsafe().c_str());
}
- return stream.str();
+ return output;
}
// Returns a duration that is longer than the test timeout. We would use
// TimeDelta::Max() but https://crbug.com/465948.
TimeDelta AVeryLongTimeDelta() { return TimeDelta::FromDays(1); }
+
} // namespace
// The tests below are enabled for Win x64 only, pending implementation of the
// tested functionality on other platforms/architectures.
-// Checks that the basic expected information is present in a sampled profile.
+// Checks that the basic expected information is present in a sampled call stack
+// profile.
#if defined(_WIN64)
#define MAYBE_Basic Basic
#else
#define MAYBE_Basic DISABLED_Basic
#endif
TEST(StackSamplingProfilerTest, MAYBE_Basic) {
- StackSamplingProfiler::SamplingParams params;
- params.initial_delay = params.burst_interval = params.sampling_interval =
- TimeDelta::FromMilliseconds(0);
- params.bursts = 1;
+ SamplingParams params;
+ params.sampling_interval = TimeDelta::FromMilliseconds(0);
params.samples_per_burst = 1;
+ params.user_data = 100;
+ params.preserve_sample_ordering = true;
- std::vector<Profile> profiles;
- CaptureProfiles(params, &profiles, AVeryLongTimeDelta());
+ std::vector<CallStackProfile> profiles;
+ CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta());
// Check that the profile and samples sizes are correct, and the module
// indices are in range.
-
ASSERT_EQ(1u, profiles.size());
- const Profile& profile = profiles[0];
+ const CallStackProfile& profile = profiles[0];
ASSERT_EQ(1u, profile.samples.size());
EXPECT_EQ(params.sampling_interval, profile.sampling_period);
const Sample& sample = profile.samples[0];
for (const auto& frame : sample) {
- ASSERT_GE(frame.module_index, 0);
- ASSERT_LT(frame.module_index, static_cast<int>(profile.modules.size()));
+ ASSERT_GE(frame.module_index, 0u);
+ ASSERT_LT(frame.module_index, profile.modules.size());
}
+ EXPECT_EQ(100u, profile.user_data);
+ EXPECT_EQ(true, profile.preserve_sample_ordering);
// Check that the stack contains a frame for
// TargetThread::SignalAndWaitUntilSignaled() and that the frame has this
// executable's module.
-
+ //
// Since we don't have a good way to know the function size, use 100 bytes as
// a reasonable window to locate the instruction pointer.
Sample::const_iterator loc = FindFirstFrameWithinFunction(
@@ -225,80 +289,76 @@
<< MaybeFixupFunctionAddressForILT(
reinterpret_cast<const void*>(
&TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:" << std::endl
+ << " was not found in stack:\n"
<< FormatSampleForDiagnosticOutput(sample, profile.modules);
-
FilePath executable_path;
- bool got_executable_path = PathService::Get(FILE_EXE, &executable_path);
- EXPECT_TRUE(got_executable_path);
+ EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename);
}
// Checks that the expected number of profiles and samples are present in the
-// profiles produced.
+// call stack profiles produced.
#if defined(_WIN64)
#define MAYBE_MultipleProfilesAndSamples MultipleProfilesAndSamples
#else
#define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples
#endif
TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) {
- StackSamplingProfiler::SamplingParams params;
- params.initial_delay = params.burst_interval = params.sampling_interval =
+ SamplingParams params;
+ params.burst_interval = params.sampling_interval =
TimeDelta::FromMilliseconds(0);
params.bursts = 2;
params.samples_per_burst = 3;
- std::vector<Profile> profiles;
- CaptureProfiles(params, &profiles, AVeryLongTimeDelta());
+ std::vector<CallStackProfile> profiles;
+ CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta());
ASSERT_EQ(2u, profiles.size());
EXPECT_EQ(3u, profiles[0].samples.size());
EXPECT_EQ(3u, profiles[1].samples.size());
}
-// Checks that no profiles are captured if the profiling is stopped during the
-// initial delay.
+// Checks that no call stack profiles are captured if the profiling is stopped
+// during the initial delay.
#if defined(_WIN64)
#define MAYBE_StopDuringInitialDelay StopDuringInitialDelay
#else
#define MAYBE_StopDuringInitialDelay DISABLED_StopDuringInitialDelay
#endif
TEST(StackSamplingProfilerTest, MAYBE_StopDuringInitialDelay) {
- StackSamplingProfiler::SamplingParams params;
- params.burst_interval = params.sampling_interval =
- TimeDelta::FromMilliseconds(0);
+ SamplingParams params;
params.initial_delay = TimeDelta::FromSeconds(60);
- params.bursts = params.samples_per_burst = 1;
- std::vector<Profile> profiles;
- CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(0));
+ std::vector<CallStackProfile> profiles;
+ CaptureProfilesWithObjectCallback(params, &profiles,
+ TimeDelta::FromMilliseconds(0));
EXPECT_TRUE(profiles.empty());
}
-// Checks that the single completed profile is captured if the profiling is
-// stopped between bursts.
+// Checks that the single completed call stack profile is captured if the
+// profiling is stopped between bursts.
#if defined(_WIN64)
#define MAYBE_StopDuringInterBurstInterval StopDuringInterBurstInterval
#else
#define MAYBE_StopDuringInterBurstInterval DISABLED_StopDuringInterBurstInterval
#endif
TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterBurstInterval) {
- StackSamplingProfiler::SamplingParams params;
- params.initial_delay = params.sampling_interval =
- TimeDelta::FromMilliseconds(0);
+ SamplingParams params;
+ params.sampling_interval = TimeDelta::FromMilliseconds(0);
params.burst_interval = TimeDelta::FromSeconds(60);
params.bursts = 2;
params.samples_per_burst = 1;
- std::vector<Profile> profiles;
- CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50));
+ std::vector<CallStackProfile> profiles;
+ CaptureProfilesWithObjectCallback(params, &profiles,
+ TimeDelta::FromMilliseconds(50));
ASSERT_EQ(1u, profiles.size());
EXPECT_EQ(1u, profiles[0].samples.size());
}
-// Checks that only completed profiles are captured.
+// Checks that only completed call stack profiles are captured.
#if defined(_WIN64)
#define MAYBE_StopDuringInterSampleInterval StopDuringInterSampleInterval
#else
@@ -306,16 +366,80 @@
DISABLED_StopDuringInterSampleInterval
#endif
TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterSampleInterval) {
- StackSamplingProfiler::SamplingParams params;
- params.initial_delay = params.burst_interval = TimeDelta::FromMilliseconds(0);
+ SamplingParams params;
params.sampling_interval = TimeDelta::FromSeconds(60);
- params.bursts = 1;
params.samples_per_burst = 2;
- std::vector<Profile> profiles;
- CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50));
+ std::vector<CallStackProfile> profiles;
+ CaptureProfilesWithObjectCallback(params, &profiles,
+ TimeDelta::FromMilliseconds(50));
EXPECT_TRUE(profiles.empty());
}
-} // namespace tracked_objects
+// Checks that profiles are captured via the default completed callback.
+#if defined(_WIN64)
+#define MAYBE_DefaultCallback DefaultCallback
+#else
+#define MAYBE_DefaultCallback DISABLED_DefaultCallback
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_DefaultCallback) {
+ SamplingParams params;
+ params.samples_per_burst = 1;
+
+ CallStackProfiles profiles;
+ CaptureProfilesWithDefaultCallback(params, &profiles);
+
+ EXPECT_EQ(1u, profiles.size());
+ EXPECT_EQ(1u, profiles[0].samples.size());
+}
+
+// Checks that profiles are queued until a default callback is set, then
+// delivered.
+#if defined(_WIN64)
+#define MAYBE_ProfilesQueuedWithNoCallback ProfilesQueuedWithNoCallback
+#else
+#define MAYBE_ProfilesQueuedWithNoCallback DISABLED_ProfilesQueuedWithNoCallback
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_ProfilesQueuedWithNoCallback) {
+ SamplingParams params;
+ params.samples_per_burst = 1;
+
+ RunProfilerWithNoCallback(params, TimeDelta::FromMilliseconds(50));
+
+ CallStackProfiles profiles;
+ // This should immediately call SaveProfiles on this thread.
+ StackSamplingProfiler::SetDefaultCompletedCallback(
+ Bind(&SaveProfiles, Unretained(&profiles)));
+ EXPECT_EQ(1u, profiles.size());
+ EXPECT_EQ(1u, profiles[0].samples.size());
+ StackSamplingProfiler::SetDefaultCompletedCallback(
+ StackSamplingProfiler::CompletedCallback());
+}
+
+// Checks that we can destroy the profiler while profiling.
+#if defined(_WIN64)
+#define MAYBE_DestroyProfilerWhileProfiling DestroyProfilerWhileProfiling
+#else
+#define MAYBE_DestroyProfilerWhileProfiling \
+ DISABLED_DestroyProfilerWhileProfiling
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_DestroyProfilerWhileProfiling) {
+ SamplingParams params;
+ params.sampling_interval = TimeDelta::FromMilliseconds(10);
+
+ CallStackProfiles profiles;
+ WithTargetThread([¶ms, &profiles](PlatformThreadId target_thread_id) {
+ scoped_ptr<StackSamplingProfiler> profiler;
+ profiler.reset(new StackSamplingProfiler(
+ target_thread_id, params, Bind(&SaveProfiles, Unretained(&profiles))));
+ profiler->Start();
+ profiler.reset();
+
+ // Wait longer than a sample interval to catch any use-after-free actions by
+ // the profiler thread.
+ PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
+ });
+}
+
+} // namespace base
diff --git a/base/profiler/stack_sampling_profiler_win.cc b/base/profiler/stack_sampling_profiler_win.cc
index ba46cf0..1ccd134 100644
--- a/base/profiler/stack_sampling_profiler_win.cc
+++ b/base/profiler/stack_sampling_profiler_win.cc
@@ -2,14 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/profiler/stack_sampling_profiler.h"
-
-#include <dbghelp.h>
-#include <map>
-#include <utility>
+#include <objbase.h>
#include <windows.h>
+#include <map>
+#include <utility>
+
#include "base/logging.h"
+#include "base/profiler/native_stack_sampler.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/pe_image.h"
#include "base/win/scoped_handle.h"
@@ -18,38 +21,7 @@
namespace {
-class NativeStackSamplerWin : public StackSamplingProfiler::NativeStackSampler {
- public:
- explicit NativeStackSamplerWin(win::ScopedHandle thread_handle);
- ~NativeStackSamplerWin() override;
-
- // StackSamplingProfiler::NativeStackSampler:
- void ProfileRecordingStarting(
- StackSamplingProfiler::Profile* profile) override;
- void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
- void ProfileRecordingStopped() override;
-
- private:
- static bool GetModuleInfo(HMODULE module,
- StackSamplingProfiler::Module* module_info);
-
- void CopyToSample(const void* const instruction_pointers[],
- const HMODULE modules[],
- int stack_depth,
- StackSamplingProfiler::Sample* sample,
- std::vector<StackSamplingProfiler::Module>* module_infos);
-
- win::ScopedHandle thread_handle_;
- // Weak. Points to the profile being recorded between
- // ProfileRecordingStarting() and ProfileRecordingStopped().
- StackSamplingProfiler::Profile* current_profile_;
- // Maps a module to the module's index within current_profile_->modules.
- std::map<HMODULE, int> profile_module_index_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
-};
-
-// Walk the stack represented by |context| from the current frame downwards,
+// Walks the stack represented by |context| from the current frame downwards,
// recording the instruction pointers for each frame in |instruction_pointers|.
int RecordStack(CONTEXT* context,
int max_stack_size,
@@ -58,69 +30,104 @@
#ifdef _WIN64
*last_frame_is_unknown_function = false;
- IMAGEHLP_SYMBOL64 sym;
- sym.SizeOfStruct = sizeof(sym);
- sym.MaxNameLength = 0;
-
- for (int i = 0; i < max_stack_size; ++i) {
+ int i = 0;
+ for (; (i < max_stack_size) && context->Rip; ++i) {
// Try to look up unwind metadata for the current function.
ULONG64 image_base;
PRUNTIME_FUNCTION runtime_function =
RtlLookupFunctionEntry(context->Rip, &image_base, nullptr);
- instruction_pointers[i] = reinterpret_cast<void*>(context->Rip);
+ instruction_pointers[i] = reinterpret_cast<const void*>(context->Rip);
if (runtime_function) {
KNONVOLATILE_CONTEXT_POINTERS nvcontext = {0};
void* handler_data;
ULONG64 establisher_frame;
RtlVirtualUnwind(0, image_base, context->Rip, runtime_function, context,
- &handler_data, &establisher_frame, &nvcontext);
+ &handler_data, &establisher_frame, &nvcontext);
} else {
- // If we don't have a RUNTIME_FUNCTION, then we've encountered
- // a leaf function. Adjust the stack appropriately.
- context->Rip = *reinterpret_cast<PDWORD64>(context->Rsp);
- context->Rsp += 8;
- *last_frame_is_unknown_function = true;
- }
-
- if (!context->Rip)
+ // If we don't have a RUNTIME_FUNCTION, then in theory this should be a
+ // leaf function whose frame contains only a return address, at
+ // RSP. However, crash data also indicates that some third party libraries
+ // do not provide RUNTIME_FUNCTION information for non-leaf functions. We
+ // could manually unwind the stack in the former case, but attempting to
+ // do so in the latter case would produce wrong results and likely crash,
+ // so just bail out.
+ //
+ // Ad hoc runs with instrumentation show that ~5% of stack traces end with
+ // a valid leaf function. To avoid selectively omitting these traces it
+ // makes sense to ultimately try to distinguish these two cases and
+ // selectively unwind the stack for legitimate leaf functions. For the
+ // purposes of avoiding crashes though, just ignore them all for now.
return i;
+ }
}
- return max_stack_size;
+ return i;
#else
return 0;
#endif
}
-// Fills in |modules| corresponding to the pointers to code in |addresses|. The
-// modules are returned with reference counts incremented should be freed with
-// FreeModules.
-void FindModulesForAddresses(const void* const addresses[], HMODULE modules[],
- int stack_depth,
+// Fills in |module_handles| corresponding to the pointers to code in
+// |addresses|. The module handles are returned with reference counts
+// incremented and should be freed with FreeModuleHandles. See note in
+// SuspendThreadAndRecordStack for why |addresses| and |module_handles| are
+// arrays.
+void FindModuleHandlesForAddresses(const void* const addresses[],
+ HMODULE module_handles[], int stack_depth,
bool last_frame_is_unknown_function) {
- const int module_frames = last_frame_is_unknown_function ? stack_depth - 1 :
- stack_depth;
+ const int module_frames =
+ last_frame_is_unknown_function ? stack_depth - 1 : stack_depth;
for (int i = 0; i < module_frames; ++i) {
- HMODULE module = NULL;
+ HMODULE module_handle = NULL;
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast<LPCTSTR>(addresses[i]),
- &module)) {
- // HMODULE is the base address of the module.
- DCHECK_LT(reinterpret_cast<const void*>(module), addresses[i]);
- modules[i] = module;
+ &module_handle)) {
+ // HMODULE actually represents the base address of the module, so we can
+ // use it directly as an address.
+ DCHECK_LE(reinterpret_cast<const void*>(module_handle), addresses[i]);
+ module_handles[i] = module_handle;
}
}
}
-// Free the modules returned by FindModulesForAddresses.
-void FreeModules(int stack_depth, HMODULE modules[]) {
+// Frees the modules handles returned by FindModuleHandlesForAddresses. See note
+// in SuspendThreadAndRecordStack for why |module_handles| is an array.
+void FreeModuleHandles(int stack_depth, HMODULE module_handles[]) {
for (int i = 0; i < stack_depth; ++i) {
- if (modules[i])
- ::FreeLibrary(modules[i]);
+ if (module_handles[i])
+ ::FreeLibrary(module_handles[i]);
}
}
+// Gets the unique build ID for a module. Windows build IDs are created by a
+// concatenation of a GUID and AGE fields found in the headers of a module. The
+// GUID is stored in the first 16 bytes and the AGE is stored in the last 4
+// bytes. Returns the empty string if the function fails to get the build ID.
+//
+// Example:
+// dumpbin chrome.exe /headers | find "Format:"
+// ... Format: RSDS, {16B2A428-1DED-442E-9A36-FCE8CBD29726}, 10, ...
+//
+// The resulting buildID string of this instance of chrome.exe is
+// "16B2A4281DED442E9A36FCE8CBD2972610".
+//
+// Note that the AGE field is encoded in decimal, not hex.
+std::string GetBuildIDForModule(HMODULE module_handle) {
+ GUID guid;
+ DWORD age;
+ win::PEImage(module_handle).GetDebugId(&guid, &age);
+ const int kGUIDSize = 39;
+ std::wstring build_id;
+ int result =
+ ::StringFromGUID2(guid, WriteInto(&build_id, kGUIDSize), kGUIDSize);
+ if (result != kGUIDSize)
+ return std::string();
+ RemoveChars(build_id, L"{}-", &build_id);
+ build_id += StringPrintf(L"%d", age);
+ return WideToUTF8(build_id);
+}
+
// Disables priority boost on a thread for the lifetime of the object.
class ScopedDisablePriorityBoost {
public:
@@ -141,185 +148,210 @@
boost_state_was_disabled_(false) {
got_previous_boost_state_ =
::GetThreadPriorityBoost(thread_handle_, &boost_state_was_disabled_);
- if (got_previous_boost_state_ && !boost_state_was_disabled_) {
- // Confusingly, TRUE disables priority boost ...
+ if (got_previous_boost_state_) {
+ // Confusingly, TRUE disables priority boost.
::SetThreadPriorityBoost(thread_handle_, TRUE);
}
}
ScopedDisablePriorityBoost::~ScopedDisablePriorityBoost() {
- if (got_previous_boost_state_ && !boost_state_was_disabled_) {
- // ... and FALSE enables priority boost.
- ::SetThreadPriorityBoost(thread_handle_, FALSE);
- }
+ if (got_previous_boost_state_)
+ ::SetThreadPriorityBoost(thread_handle_, boost_state_was_disabled_);
}
// Suspends the thread with |thread_handle|, records the stack into
// |instruction_pointers|, then resumes the thread. Returns the size of the
// stack.
+//
+// IMPORTANT NOTE: No heap allocations may occur between SuspendThread and
+// ResumeThread. Otherwise this code can deadlock on heap locks acquired by the
+// target thread before it was suspended. This is why we pass instruction
+// pointers and module handles as preallocated arrays rather than vectors, since
+// vectors make it too easy to subtly allocate memory.
int SuspendThreadAndRecordStack(HANDLE thread_handle, int max_stack_size,
const void* instruction_pointers[],
bool* last_frame_is_unknown_function) {
-#if defined(_WIN64)
- if (RtlVirtualUnwind == nullptr || RtlLookupFunctionEntry == nullptr)
+ if (::SuspendThread(thread_handle) == -1)
return 0;
-#endif
- if (::SuspendThread(thread_handle) == -1) {
- LOG(ERROR) << "SuspendThread failed: " << GetLastError();
- return 0;
- }
-
+ int stack_depth = 0;
CONTEXT thread_context = {0};
thread_context.ContextFlags = CONTEXT_FULL;
- if (!::GetThreadContext(thread_handle, &thread_context)) {
- LOG(ERROR) << "GetThreadContext failed: " << GetLastError();
+ if (::GetThreadContext(thread_handle, &thread_context)) {
+ stack_depth = RecordStack(&thread_context, max_stack_size,
+ instruction_pointers,
+ last_frame_is_unknown_function);
}
- int stack_depth = RecordStack(&thread_context, max_stack_size,
- instruction_pointers,
- last_frame_is_unknown_function);
-
- {
- ScopedDisablePriorityBoost disable_priority_boost(thread_handle);
- if (::ResumeThread(thread_handle) == -1)
- LOG(ERROR) << "ResumeThread failed: " << GetLastError();
- }
+ // Disable the priority boost that the thread would otherwise receive on
+ // resume. We do this to avoid artificially altering the dynamics of the
+ // executing application any more than we already are by suspending and
+ // resuming the thread.
+ //
+ // Note that this can racily disable a priority boost that otherwise would
+ // have been given to the thread, if the thread is waiting on other wait
+ // conditions at the time of SuspendThread and those conditions are satisfied
+ // before priority boost is reenabled. The measured length of this window is
+ // ~100us, so this should occur fairly rarely.
+ ScopedDisablePriorityBoost disable_priority_boost(thread_handle);
+ bool resume_thread_succeeded = ::ResumeThread(thread_handle) != -1;
+ CHECK(resume_thread_succeeded) << "ResumeThread failed: " << GetLastError();
return stack_depth;
}
-} // namespace
+class NativeStackSamplerWin : public NativeStackSampler {
+ public:
+ explicit NativeStackSamplerWin(win::ScopedHandle thread_handle);
+ ~NativeStackSamplerWin() override;
-scoped_ptr<StackSamplingProfiler::NativeStackSampler>
-StackSamplingProfiler::NativeStackSampler::Create(PlatformThreadId thread_id) {
-#if _WIN64
- // Get the thread's handle.
- HANDLE thread_handle = ::OpenThread(
- THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
- FALSE,
- thread_id);
- DCHECK(thread_handle) << "OpenThread failed";
+ // StackSamplingProfiler::NativeStackSampler:
+ void ProfileRecordingStarting(
+ std::vector<StackSamplingProfiler::Module>* modules) override;
+ void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
+ void ProfileRecordingStopped() override;
- return scoped_ptr<NativeStackSampler>(new NativeStackSamplerWin(
- win::ScopedHandle(thread_handle)));
-#else
- return scoped_ptr<NativeStackSampler>();
-#endif
-}
+ private:
+ // Attempts to query the module filename, base address, and id for
+ // |module_handle|, and store them in |module|. Returns true if it succeeded.
+ static bool GetModuleForHandle(HMODULE module_handle,
+ StackSamplingProfiler::Module* module);
+
+ // Gets the index for the Module corresponding to |module_handle| in
+ // |modules|, adding it if it's not already present. Returns
+ // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be
+ // determined for |module|.
+ size_t GetModuleIndex(HMODULE module_handle,
+ std::vector<StackSamplingProfiler::Module>* modules);
+
+ // Copies the stack information represented by |instruction_pointers| into
+ // |sample| and |modules|.
+ void CopyToSample(const void* const instruction_pointers[],
+ const HMODULE module_handles[],
+ int stack_depth,
+ StackSamplingProfiler::Sample* sample,
+ std::vector<StackSamplingProfiler::Module>* modules);
+
+ win::ScopedHandle thread_handle_;
+ // Weak. Points to the modules associated with the profile being recorded
+ // between ProfileRecordingStarting() and ProfileRecordingStopped().
+ std::vector<StackSamplingProfiler::Module>* current_modules_;
+ // Maps a module handle to the corresponding Module's index within
+ // current_modules_.
+ std::map<HMODULE, size_t> profile_module_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
+};
NativeStackSamplerWin::NativeStackSamplerWin(win::ScopedHandle thread_handle)
: thread_handle_(thread_handle.Take()) {
-#ifdef _WIN64
- if (RtlVirtualUnwind == nullptr && RtlLookupFunctionEntry == nullptr) {
- const HMODULE nt_dll_handle = ::GetModuleHandle(L"ntdll.dll");
- // This should always be non-null, but handle just in case.
- if (nt_dll_handle) {
- reinterpret_cast<void*&>(RtlVirtualUnwind) =
- ::GetProcAddress(nt_dll_handle, "RtlVirtualUnwind");
- reinterpret_cast<void*&>(RtlLookupFunctionEntry) =
- ::GetProcAddress(nt_dll_handle, "RtlLookupFunctionEntry");
- }
- }
-#endif
}
NativeStackSamplerWin::~NativeStackSamplerWin() {
}
void NativeStackSamplerWin::ProfileRecordingStarting(
- StackSamplingProfiler::Profile* profile) {
- current_profile_ = profile;
+ std::vector<StackSamplingProfiler::Module>* modules) {
+ current_modules_ = modules;
profile_module_index_.clear();
}
void NativeStackSamplerWin::RecordStackSample(
StackSamplingProfiler::Sample* sample) {
- DCHECK(current_profile_);
+ DCHECK(current_modules_);
const int max_stack_size = 64;
const void* instruction_pointers[max_stack_size] = {0};
- HMODULE modules[max_stack_size] = {0};
+ HMODULE module_handles[max_stack_size] = {0};
bool last_frame_is_unknown_function = false;
int stack_depth = SuspendThreadAndRecordStack(
thread_handle_.Get(), max_stack_size, instruction_pointers,
&last_frame_is_unknown_function);
- FindModulesForAddresses(instruction_pointers, modules, stack_depth,
- last_frame_is_unknown_function);
- CopyToSample(instruction_pointers, modules, stack_depth, sample,
- ¤t_profile_->modules);
- FreeModules(stack_depth, modules);
+ FindModuleHandlesForAddresses(instruction_pointers, module_handles,
+ stack_depth, last_frame_is_unknown_function);
+ CopyToSample(instruction_pointers, module_handles, stack_depth, sample,
+ current_modules_);
+ FreeModuleHandles(stack_depth, module_handles);
}
void NativeStackSamplerWin::ProfileRecordingStopped() {
- current_profile_ = nullptr;
+ current_modules_ = nullptr;
}
// static
-bool NativeStackSamplerWin::GetModuleInfo(
- HMODULE module,
- StackSamplingProfiler::Module* module_info) {
+bool NativeStackSamplerWin::GetModuleForHandle(
+ HMODULE module_handle,
+ StackSamplingProfiler::Module* module) {
wchar_t module_name[MAX_PATH];
DWORD result_length =
- GetModuleFileName(module, module_name, arraysize(module_name));
+ GetModuleFileName(module_handle, module_name, arraysize(module_name));
if (result_length == 0)
return false;
- module_info->filename = base::FilePath(module_name);
+ module->filename = base::FilePath(module_name);
- module_info->base_address = reinterpret_cast<const void*>(module);
+ module->base_address = reinterpret_cast<const void*>(module_handle);
- GUID guid;
- DWORD age;
- win::PEImage(module).GetDebugId(&guid, &age);
- module_info->id.insert(module_info->id.end(),
- reinterpret_cast<char*>(&guid),
- reinterpret_cast<char*>(&guid + 1));
- module_info->id.insert(module_info->id.end(),
- reinterpret_cast<char*>(&age),
- reinterpret_cast<char*>(&age + 1));
+ module->id = GetBuildIDForModule(module_handle);
+ if (module->id.empty())
+ return false;
return true;
}
+size_t NativeStackSamplerWin::GetModuleIndex(
+ HMODULE module_handle,
+ std::vector<StackSamplingProfiler::Module>* modules) {
+ if (!module_handle)
+ return StackSamplingProfiler::Frame::kUnknownModuleIndex;
+
+ auto loc = profile_module_index_.find(module_handle);
+ if (loc == profile_module_index_.end()) {
+ StackSamplingProfiler::Module module;
+ if (!GetModuleForHandle(module_handle, &module))
+ return StackSamplingProfiler::Frame::kUnknownModuleIndex;
+ modules->push_back(module);
+ loc = profile_module_index_.insert(std::make_pair(
+ module_handle, modules->size() - 1)).first;
+ }
+
+ return loc->second;
+}
+
void NativeStackSamplerWin::CopyToSample(
const void* const instruction_pointers[],
- const HMODULE modules[],
+ const HMODULE module_handles[],
int stack_depth,
StackSamplingProfiler::Sample* sample,
- std::vector<StackSamplingProfiler::Module>* module_infos) {
+ std::vector<StackSamplingProfiler::Module>* module) {
sample->clear();
sample->reserve(stack_depth);
for (int i = 0; i < stack_depth; ++i) {
- sample->push_back(StackSamplingProfiler::Frame());
- StackSamplingProfiler::Frame& frame = sample->back();
-
- frame.instruction_pointer = instruction_pointers[i];
-
- // Record an invalid module index if we don't have a valid module.
- if (!modules[i]) {
- frame.module_index = -1;
- continue;
- }
-
- auto loc = profile_module_index_.find(modules[i]);
- if (loc == profile_module_index_.end()) {
- StackSamplingProfiler::Module module_info;
- // Record an invalid module index if we have a module but can't find
- // information on it.
- if (!GetModuleInfo(modules[i], &module_info)) {
- frame.module_index = -1;
- continue;
- }
- module_infos->push_back(module_info);
- loc = profile_module_index_.insert(std::make_pair(
- modules[i], static_cast<int>(module_infos->size() - 1))).first;
- }
-
- frame.module_index = loc->second;
+ sample->push_back(StackSamplingProfiler::Frame(
+ instruction_pointers[i],
+ GetModuleIndex(module_handles[i], module)));
}
}
+} // namespace
+
+scoped_ptr<NativeStackSampler> NativeStackSampler::Create(
+ PlatformThreadId thread_id) {
+#if _WIN64
+ // Get the thread's handle.
+ HANDLE thread_handle = ::OpenThread(
+ THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
+ FALSE,
+ thread_id);
+
+ if (thread_handle) {
+ return scoped_ptr<NativeStackSampler>(new NativeStackSamplerWin(
+ win::ScopedHandle(thread_handle)));
+ }
+#endif
+ return scoped_ptr<NativeStackSampler>();
+}
+
} // namespace base
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index f4c60a7..07ba6f5 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -69,7 +69,7 @@
// We also use it so that the compiler doesn't discard certain return values
// as something we don't need (see the comment with calloc below).
template <typename Type>
-Type HideValueFromCompiler(volatile Type value) {
+NOINLINE Type HideValueFromCompiler(volatile Type value) {
#if defined(__GNUC__)
// In a GCC compatible compiler (GCC or Clang), make this compiler barrier
// more robust than merely using "volatile".
@@ -293,8 +293,8 @@
scoped_ptr<char, base::FreeDeleter> array_pointer(
static_cast<char*>(calloc(nmemb, size)));
// We need the call to HideValueFromCompiler(): we have seen LLVM
- // optimize away the call to calloc() entirely and assume
- // the pointer to not be NULL.
+ // optimize away the call to calloc() entirely and assume the pointer to not
+ // be NULL.
return HideValueFromCompiler(array_pointer.get()) == NULL;
}
diff --git a/base/stl_util.h b/base/stl_util.h
index 89a53b0..e937d2f 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -90,6 +90,14 @@
}
}
+// Counts the number of instances of val in a container.
+template <typename Container, typename T>
+typename std::iterator_traits<
+ typename Container::const_iterator>::difference_type
+STLCount(const Container& container, const T& val) {
+ return std::count(container.begin(), container.end(), val);
+}
+
// To treat a possibly-empty vector as an array, use these functions.
// If you know the array will never be empty, you can use &*v.begin()
// directly, but that is undefined behaviour if |v| is empty.
@@ -195,6 +203,14 @@
return collection.find(key) != collection.end();
}
+// Test to see if a collection like a vector contains a particular value.
+// Returns true if the value is in the collection.
+template <typename Collection, typename Value>
+bool ContainsValue(const Collection& collection, const Value& value) {
+ return std::find(collection.begin(), collection.end(), value) !=
+ collection.end();
+}
+
namespace base {
// Returns true if the container is sorted.
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index 692f300..88a6236 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
#include "base/third_party/icu/icu_utf.h"
namespace base {
@@ -193,7 +192,6 @@
void SplitStringDontTrim(const std::string& str,
char c,
std::vector<std::string>* r) {
- DCHECK(IsStringUTF8(str));
#if CHAR_MIN < 0
DCHECK_GE(c, 0);
#endif
diff --git a/base/sync_socket.h b/base/sync_socket.h
index 4da9d3b..36d6bc1 100644
--- a/base/sync_socket.h
+++ b/base/sync_socket.h
@@ -124,11 +124,11 @@
// and there isn't a way to cancel a blocking synchronous Read that is
// supported on <Vista. So, for Windows only, we override these
// SyncSocket methods in order to support shutting down the 'socket'.
- virtual bool Close() override;
- virtual size_t Receive(void* buffer, size_t length) override;
- virtual size_t ReceiveWithTimeout(void* buffer,
- size_t length,
- TimeDelta timeout) override;
+ bool Close() override;
+ size_t Receive(void* buffer, size_t length) override;
+ size_t ReceiveWithTimeout(void* buffer,
+ size_t length,
+ TimeDelta timeout) override;
#endif
// Send() is overridden to catch cases where the remote end is not responding
diff --git a/base/synchronization/cancellation_flag.cc b/base/synchronization/cancellation_flag.cc
index ad3b551..ca5c0a8 100644
--- a/base/synchronization/cancellation_flag.cc
+++ b/base/synchronization/cancellation_flag.cc
@@ -19,4 +19,8 @@
return base::subtle::Acquire_Load(&flag_) != 0;
}
+void CancellationFlag::UnsafeResetForTesting() {
+ base::subtle::Release_Store(&flag_, 0);
+}
+
} // namespace base
diff --git a/base/synchronization/cancellation_flag.h b/base/synchronization/cancellation_flag.h
index 51a4def..0f0f08e 100644
--- a/base/synchronization/cancellation_flag.h
+++ b/base/synchronization/cancellation_flag.h
@@ -29,6 +29,11 @@
void Set();
bool IsSet() const; // Returns true iff the flag was set.
+ // For subtle reasons that may be different on different architectures,
+ // a different thread testing IsSet() may erroneously read 'true' after
+ // this method has been called.
+ void UnsafeResetForTesting();
+
private:
base::subtle::Atomic32 flag_;
#if !defined(NDEBUG)
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc
index 6dc4831..5f165c8 100644
--- a/base/synchronization/condition_variable_win.cc
+++ b/base/synchronization/condition_variable_win.cc
@@ -72,12 +72,12 @@
class WinVistaCondVar: public ConditionVarImpl {
public:
WinVistaCondVar(Lock* user_lock);
- ~WinVistaCondVar() {};
+ ~WinVistaCondVar() override {}
// Overridden from ConditionVarImpl.
- virtual void Wait() override;
- virtual void TimedWait(const TimeDelta& max_time) override;
- virtual void Broadcast() override;
- virtual void Signal() override;
+ void Wait() override;
+ void TimedWait(const TimeDelta& max_time) override;
+ void Broadcast() override;
+ void Signal() override;
private:
base::Lock& user_lock_;
@@ -127,12 +127,12 @@
class WinXPCondVar : public ConditionVarImpl {
public:
WinXPCondVar(Lock* user_lock);
- ~WinXPCondVar();
+ ~WinXPCondVar() override;
// Overridden from ConditionVarImpl.
- virtual void Wait() override;
- virtual void TimedWait(const TimeDelta& max_time) override;
- virtual void Broadcast() override;
- virtual void Signal() override;
+ void Wait() override;
+ void TimedWait(const TimeDelta& max_time) override;
+ void Broadcast() override;
+ void Signal() override;
// Define Event class that is used to form circularly linked lists.
// The list container is an element with NULL as its handle_ value.
diff --git a/base/synchronization/waitable_event_unittest.cc b/base/synchronization/waitable_event_unittest.cc
index abba935..be56cf1 100644
--- a/base/synchronization/waitable_event_unittest.cc
+++ b/base/synchronization/waitable_event_unittest.cc
@@ -73,29 +73,27 @@
class WaitableEventSignaler : public PlatformThread::Delegate {
public:
- WaitableEventSignaler(double seconds, WaitableEvent* ev)
- : seconds_(seconds),
- ev_(ev) {
+ WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
+ : delay_(delay),
+ event_(event) {
}
void ThreadMain() override {
- PlatformThread::Sleep(TimeDelta::FromSecondsD(seconds_));
- ev_->Signal();
+ PlatformThread::Sleep(delay_);
+ event_->Signal();
}
private:
- const double seconds_;
- WaitableEvent *const ev_;
+ const TimeDelta delay_;
+ WaitableEvent* event_;
};
+// Tests that a WaitableEvent can be safely deleted when |Wait| is done without
+// additional synchronization.
TEST(WaitableEventTest, WaitAndDelete) {
- // This test tests that if a WaitableEvent can be safely deleted
- // when |Wait| is done without additional synchrnization.
- // If this test crashes, it is a bug.
-
WaitableEvent* ev = new WaitableEvent(false, false);
- WaitableEventSignaler signaler(0.01, ev);
+ WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
PlatformThreadHandle thread;
PlatformThread::Create(0, &signaler, &thread);
@@ -105,16 +103,14 @@
PlatformThread::Join(thread);
}
+// Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
+// without additional synchronization.
TEST(WaitableEventTest, WaitMany) {
- // This test tests that if a WaitableEvent can be safely deleted
- // when |WaitMany| is done without additional synchrnization.
- // If this test crashes, it is a bug.
-
WaitableEvent* ev[5];
for (unsigned i = 0; i < 5; ++i)
ev[i] = new WaitableEvent(false, false);
- WaitableEventSignaler signaler(0.01, ev[2]);
+ WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
PlatformThreadHandle thread;
PlatformThread::Create(0, &signaler, &thread);
@@ -127,4 +123,28 @@
EXPECT_EQ(2u, index);
}
+// Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
+// a timeout of 0. (crbug.com/465948)
+#if defined(OS_POSIX)
+// crbug.com/465948 not fixed yet.
+#define MAYBE_TimedWait DISABLED_TimedWait
+#else
+#define MAYBE_TimedWait TimedWait
+#endif
+TEST(WaitableEventTest, MAYBE_TimedWait) {
+ WaitableEvent* ev = new WaitableEvent(false, false);
+
+ TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
+ WaitableEventSignaler signaler(thread_delay, ev);
+ PlatformThreadHandle thread;
+ TimeTicks start = TimeTicks::Now();
+ PlatformThread::Create(0, &signaler, &thread);
+
+ ev->TimedWait(TimeDelta::Max());
+ EXPECT_GE(TimeTicks::Now() - start, thread_delay);
+ delete ev;
+
+ PlatformThread::Join(thread);
+}
+
} // namespace base
diff --git a/base/synchronization/waitable_event_watcher.h b/base/synchronization/waitable_event_watcher.h
index d4d8e77..eb51eff 100644
--- a/base/synchronization/waitable_event_watcher.h
+++ b/base/synchronization/waitable_event_watcher.h
@@ -92,7 +92,7 @@
private:
#if defined(OS_WIN)
- virtual void OnObjectSignaled(HANDLE h) override;
+ void OnObjectSignaled(HANDLE h) override;
win::ObjectWatcher watcher_;
#else
// Implementation of MessageLoop::DestructionObserver
diff --git a/base/synchronization/waitable_event_win.cc b/base/synchronization/waitable_event_win.cc
index 770c582..4db5627 100644
--- a/base/synchronization/waitable_event_win.cc
+++ b/base/synchronization/waitable_event_win.cc
@@ -4,10 +4,10 @@
#include "base/synchronization/waitable_event.h"
-#include <math.h>
#include <windows.h>
#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
@@ -37,7 +37,7 @@
}
bool WaitableEvent::IsSignaled() {
- return TimedWait(TimeDelta::FromMilliseconds(0));
+ return TimedWait(TimeDelta());
}
void WaitableEvent::Wait() {
@@ -50,13 +50,13 @@
bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
base::ThreadRestrictions::AssertWaitAllowed();
- DCHECK(max_time >= TimeDelta::FromMicroseconds(0));
- // Be careful here. TimeDelta has a precision of microseconds, but this API
- // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6?
- // It should be 6 to avoid returning too early.
- double timeout = ceil(max_time.InMillisecondsF());
- DWORD result = WaitForSingleObject(handle_.Get(),
- static_cast<DWORD>(timeout));
+ DCHECK_GE(max_time, TimeDelta());
+ // Truncate the timeout to milliseconds. The API specifies that this method
+ // can return in less than |max_time| (when returning false), as the argument
+ // is the maximum time that a caller is willing to wait.
+ DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds());
+
+ DWORD result = WaitForSingleObject(handle_.Get(), timeout);
switch (result) {
case WAIT_OBJECT_0:
return true;
diff --git a/base/sys_info.h b/base/sys_info.h
index d3476d9..654d694 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -48,10 +48,6 @@
// or -1 on failure.
static int64 AmountOfFreeDiskSpace(const FilePath& path);
- // Determine whether the device that services |path| has a seek penalty.
- // Returns false if it couldn't be determined (e.g., |path| doesn't exist).
- static bool HasSeekPenalty(const FilePath& path, bool* has_seek_penalty);
-
// Returns system uptime in milliseconds.
static int64 Uptime();
@@ -98,7 +94,7 @@
#if defined(OS_POSIX) && !defined(OS_MACOSX)
// Returns the maximum SysV shared memory segment size, or zero if there is no
// limit.
- static size_t MaxSharedMemorySize();
+ static uint64 MaxSharedMemorySize();
#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
#if defined(OS_CHROMEOS)
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
index 0f2abc5..245097f 100644
--- a/base/sys_info_android.cc
+++ b/base/sys_info_android.cc
@@ -155,12 +155,6 @@
namespace base {
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- // Find a case where this is incorrect and dbeam@ will buy you a beer.
- *has_seek_penalty = false;
- return true;
-}
-
std::string SysInfo::OperatingSystemName() {
return "Android";
}
diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc
index 2a5f5d7..ef5f1fe 100644
--- a/base/sys_info_chromeos.cc
+++ b/base/sys_info_chromeos.cc
@@ -169,11 +169,6 @@
} // namespace
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- // TODO(dbeam): implement. Can we just use boards/models?
- return false;
-}
-
// static
void SysInfo::OperatingSystemVersionNumbers(int32* major_version,
int32* minor_version,
diff --git a/base/sys_info_freebsd.cc b/base/sys_info_freebsd.cc
index 338f1cd..515b59d 100644
--- a/base/sys_info_freebsd.cc
+++ b/base/sys_info_freebsd.cc
@@ -22,19 +22,15 @@
return static_cast<int64>(pages) * page_size;
}
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- return false;
-}
-
// static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
size_t limit;
size_t size = sizeof(limit);
if (sysctlbyname("kern.ipc.shmmax", &limit, &size, NULL, 0) < 0) {
NOTREACHED();
return 0;
}
- return limit;
+ return static_cast<uint64>(limit);
}
} // namespace base
diff --git a/base/sys_info_ios.mm b/base/sys_info_ios.mm
index 324bef6..49d618c 100644
--- a/base/sys_info_ios.mm
+++ b/base/sys_info_ios.mm
@@ -16,12 +16,6 @@
namespace base {
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- // Find a case where this is incorrect and dbeam@ will buy you a beer.
- *has_seek_penalty = false;
- return true;
-}
-
// static
std::string SysInfo::OperatingSystemName() {
static dispatch_once_t get_system_name_once;
diff --git a/base/sys_info_linux.cc b/base/sys_info_linux.cc
index 401d55c..1bbfe9c 100644
--- a/base/sys_info_linux.cc
+++ b/base/sys_info_linux.cc
@@ -9,6 +9,7 @@
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info_internal.h"
@@ -28,7 +29,7 @@
return AmountOfMemory(_SC_PHYS_PAGES);
}
-size_t MaxSharedMemorySize() {
+uint64 MaxSharedMemorySize() {
std::string contents;
base::ReadFileToString(base::FilePath("/proc/sys/kernel/shmmax"), &contents);
DCHECK(!contents.empty());
@@ -40,18 +41,15 @@
if (!base::StringToUint64(contents, &limit)) {
limit = 0;
}
- if (limit > std::numeric_limits<size_t>::max()) {
- limit = 0;
- }
DCHECK_GT(limit, 0u);
- return static_cast<size_t>(limit);
+ return limit;
}
base::LazyInstance<
base::internal::LazySysInfoValue<int64, AmountOfPhysicalMemory> >::Leaky
g_lazy_physical_memory = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<
- base::internal::LazySysInfoValue<size_t, MaxSharedMemorySize> >::Leaky
+ base::internal::LazySysInfoValue<uint64, MaxSharedMemorySize> >::Leaky
g_lazy_max_shared_memory = LAZY_INSTANCE_INITIALIZER;
} // namespace
@@ -68,15 +66,8 @@
return g_lazy_physical_memory.Get().value();
}
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- // TODO(dbeam): implement.
- return false;
-}
-#endif
-
// static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
return g_lazy_max_shared_memory.Get().value();
}
diff --git a/base/sys_info_mac.cc b/base/sys_info_mac.cc
index 8635088..18df624 100644
--- a/base/sys_info_mac.cc
+++ b/base/sys_info_mac.cc
@@ -76,11 +76,6 @@
vm_info.free_count - vm_info.speculative_count) * PAGE_SIZE;
}
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- // TODO(dbeam): implement.
- return false;
-}
-
// static
std::string SysInfo::CPUModelName() {
char name[256];
diff --git a/base/sys_info_openbsd.cc b/base/sys_info_openbsd.cc
index 68d2ea1..595291b 100644
--- a/base/sys_info_openbsd.cc
+++ b/base/sys_info_openbsd.cc
@@ -48,12 +48,8 @@
return AmountOfMemory(_SC_AVPHYS_PAGES);
}
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- return false;
-}
-
// static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
int mib[] = { CTL_KERN, KERN_SHMINFO, KERN_SHMINFO_SHMMAX };
size_t limit;
size_t size = sizeof(limit);
@@ -61,7 +57,7 @@
NOTREACHED();
return 0;
}
- return limit;
+ return static_cast<uint64>(limit);
}
// static
diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc
index da47861..15ae098 100644
--- a/base/sys_info_unittest.cc
+++ b/base/sys_info_unittest.cc
@@ -41,13 +41,6 @@
<< tmp_path.value();
}
-TEST_F(SysInfoTest, HasSeekPenalty) {
- FilePath tmp_path;
- ASSERT_TRUE(base::GetTempDir(&tmp_path));
- bool unused;
- base::SysInfo::HasSeekPenalty(tmp_path, &unused);
-}
-
#if defined(OS_WIN) || defined(OS_MACOSX)
TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
int32 os_major_version = -1;
diff --git a/base/sys_info_win.cc b/base/sys_info_win.cc
index 817992c..c8314c7 100644
--- a/base/sys_info_win.cc
+++ b/base/sys_info_win.cc
@@ -1,13 +1,11 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/sys_info.h"
#include <windows.h>
-#include <winioctl.h>
-#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -65,44 +63,6 @@
return rv < 0 ? kint64max : rv;
}
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
- ThreadRestrictions::AssertIOAllowed();
-
- DCHECK(path.IsAbsolute());
- DCHECK(has_seek_penalty);
-
- // TODO(dbeam): Vista, XP support.
- if (win::GetVersion() < win::VERSION_WIN7)
- return false;
-
- std::vector<FilePath::StringType> components;
- path.GetComponents(&components);
-
- File drive(FilePath(L"\\\\.\\" + components[0]), File::FLAG_OPEN);
- if (!drive.IsValid())
- return false;
-
- STORAGE_PROPERTY_QUERY query = {};
- query.QueryType = PropertyStandardQuery;
- query.PropertyId = StorageDeviceSeekPenaltyProperty;
-
- DEVICE_SEEK_PENALTY_DESCRIPTOR result;
- DWORD bytes_returned;
-
- BOOL success = DeviceIoControl(drive.GetPlatformFile(),
- IOCTL_STORAGE_QUERY_PROPERTY,
- &query, sizeof(query),
- &result, sizeof(result),
- &bytes_returned,
- NULL);
- if (success == FALSE || bytes_returned < sizeof(result))
- return false;
-
- *has_seek_penalty = result.IncursSeekPenalty != FALSE;
- return true;
-}
-
-// static
std::string SysInfo::OperatingSystemName() {
return "Windows NT";
}
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index c4356cb..91456db 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -50,6 +50,8 @@
"mock_chrome_application_mac.mm",
"mock_devices_changed_observer.cc",
"mock_devices_changed_observer.h",
+ "mock_entropy_provider.cc",
+ "mock_entropy_provider.h",
"mock_log.cc",
"mock_log.h",
"multiprocess_test.cc",
@@ -116,6 +118,8 @@
"trace_event_analyzer.h",
"trace_to_file.cc",
"trace_to_file.h",
+ "user_action_tester.cc",
+ "user_action_tester.h",
"values_test_util.cc",
"values_test_util.h",
]
@@ -183,6 +187,18 @@
]
}
+if (is_linux) {
+ shared_library("malloc_wrapper") {
+ testonly = true
+ sources = [
+ "malloc_wrapper.cc",
+ ]
+ deps = [
+ "//base",
+ ]
+ }
+}
+
if (is_android) {
generate_jni("base_unittests_jni_headers") {
sources = [
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java b/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
index ca6e73b..8765def 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
@@ -29,12 +29,12 @@
Writer writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
- writer.write("<html><meta charset=\"UTF-8\" />" +
- "<head><title>" + title + "</title></head>" +
- "<body>" +
- (body != null ? body : "") +
- "</body>" +
- "</html>");
+ writer.write("<html><meta charset=\"UTF-8\" />"
+ + " <head><title>" + title + "</title></head>"
+ + " <body>"
+ + (body != null ? body : "")
+ + " </body>"
+ + " </html>");
} finally {
if (writer != null) {
writer.close();
@@ -61,8 +61,8 @@
try {
File f = new File(fileName);
if (f.length() > sizeLimit) {
- throw new IOException("File " + fileName + " length " + f.length() +
- " exceeds limit " + sizeLimit);
+ throw new IOException("File " + fileName + " length " + f.length()
+ + " exceeds limit " + sizeLimit);
}
char[] buffer = new char[(int) f.length()];
reader = new InputStreamReader(new FileInputStream(f), "UTF-8");
diff --git a/base/test/gtest_xml_util.h b/base/test/gtest_xml_util.h
index f832cde..9ff2406 100644
--- a/base/test/gtest_xml_util.h
+++ b/base/test/gtest_xml_util.h
@@ -21,17 +21,17 @@
class XmlUnitTestResultPrinter : public testing::EmptyTestEventListener {
public:
XmlUnitTestResultPrinter();
- virtual ~XmlUnitTestResultPrinter();
+ ~XmlUnitTestResultPrinter() override;
// Must be called before adding as a listener. Returns true on success.
bool Initialize(const FilePath& output_file_path) WARN_UNUSED_RESULT;
private:
// testing::EmptyTestEventListener:
- virtual void OnTestCaseStart(const testing::TestCase& test_case) override;
- virtual void OnTestStart(const testing::TestInfo& test_info) override;
- virtual void OnTestEnd(const testing::TestInfo& test_info) override;
- virtual void OnTestCaseEnd(const testing::TestCase& test_case) override;
+ void OnTestCaseStart(const testing::TestCase& test_case) override;
+ void OnTestStart(const testing::TestInfo& test_info) override;
+ void OnTestEnd(const testing::TestInfo& test_info) override;
+ void OnTestCaseEnd(const testing::TestCase& test_case) override;
FILE* output_file_;
diff --git a/base/test/ios/OWNERS b/base/test/ios/OWNERS
new file mode 100644
index 0000000..1b3348e
--- /dev/null
+++ b/base/test/ios/OWNERS
@@ -0,0 +1,2 @@
+rohitrao@chromium.org
+stuartmorgan@chromium.org
diff --git a/base/test/ios/wait_util.h b/base/test/ios/wait_util.h
new file mode 100644
index 0000000..01c6fe7
--- /dev/null
+++ b/base/test/ios/wait_util.h
@@ -0,0 +1,49 @@
+// 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 BASE_TEST_IOS_WAIT_UTIL_H_
+#define BASE_TEST_IOS_WAIT_UTIL_H_
+
+#include "base/ios/block_types.h"
+#include "base/time/time.h"
+
+namespace base {
+
+class MessageLoop;
+
+namespace test {
+namespace ios {
+
+// Returns the time spent in running |action| plus waiting until |condition| is
+// met.
+// Performs |action| and then spins run loop and runs the |message_loop| until
+// |condition| block returns true.
+// |action| may be nil if no action needs to be performed before the wait loop.
+// |message_loop| can be null if there is no need to spin the message loop.
+// |condition| may be nil if there is no condition to wait for: the run loop
+// will spin until timeout is reached.
+// |timeout| parameter sets the maximum wait time. If |timeout| is zero,
+// a reasonable default will be used.
+TimeDelta TimeUntilCondition(ProceduralBlock action,
+ ConditionBlock condition,
+ MessageLoop* message_loop,
+ TimeDelta timeout);
+
+// Waits until |condition| is met. A |message_loop| to spin and a |timeout| can
+// be optionally passed; if |timeout| is zero, a reasonable default will be
+// used.
+void WaitUntilCondition(ConditionBlock condition,
+ MessageLoop* message_loop,
+ TimeDelta timeout);
+void WaitUntilCondition(ConditionBlock condition);
+
+// Lets the run loop of the current thread process other messages
+// within the given maximum delay.
+void SpinRunLoopWithMaxDelay(TimeDelta max_delay);
+
+} // namespace ios
+} // namespace test
+} // namespace base
+
+#endif // BASE_TEST_IOS_WAIT_UTIL_H_
diff --git a/base/test/ios/wait_util.mm b/base/test/ios/wait_util.mm
new file mode 100644
index 0000000..e8b3a0f
--- /dev/null
+++ b/base/test/ios/wait_util.mm
@@ -0,0 +1,62 @@
+// 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.
+
+#import "base/test/ios/wait_util.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/timer/elapsed_timer.h"
+
+namespace base {
+namespace test {
+namespace ios {
+
+TimeDelta TimeUntilCondition(ProceduralBlock action,
+ ConditionBlock condition,
+ MessageLoop* message_loop,
+ TimeDelta timeout) {
+ ElapsedTimer timer;
+ if (action)
+ action();
+ if (timeout == TimeDelta())
+ timeout = TestTimeouts::action_timeout();
+ const TimeDelta spin_delay(TimeDelta::FromMilliseconds(10));
+ while (timer.Elapsed() < timeout && (!condition || !condition())) {
+ SpinRunLoopWithMaxDelay(spin_delay);
+ if (message_loop) {
+ message_loop->RunUntilIdle();
+ }
+ }
+ TimeDelta elapsed = timer.Elapsed();
+ // If DCHECK is ever hit, check if |action| is doing something that is
+ // taking an unreasonably long time, or if |condition| does not come
+ // true quickly enough. Increase |timeout| only if necessary.
+ DCHECK(!condition || condition());
+ return elapsed;
+}
+
+void WaitUntilCondition(ConditionBlock condition,
+ MessageLoop* message_loop,
+ TimeDelta timeout) {
+ TimeUntilCondition(nil, condition, message_loop, timeout);
+}
+
+void WaitUntilCondition(ConditionBlock condition) {
+ WaitUntilCondition(condition, nullptr, TimeDelta());
+}
+
+void SpinRunLoopWithMaxDelay(TimeDelta max_delay) {
+ scoped_nsobject<NSDate> beforeDate(
+ [[NSDate alloc] initWithTimeIntervalSinceNow:max_delay.InSecondsF()]);
+ [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
+ beforeDate:beforeDate];
+}
+
+} // namespace ios
+} // namespace test
+} // namespace base
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 1d48060..521f69c 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -150,7 +150,7 @@
KillSpawnedTestProcesses();
// The signal would normally kill the process, so exit now.
- exit(1);
+ _exit(1);
}
void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
@@ -310,7 +310,7 @@
exit_code = -1; // Set a non-zero exit code to signal a failure.
// Ensure that the process terminates.
- KillProcess(process.Handle(), -1, true);
+ process.Terminate(-1, true);
}
{
@@ -570,7 +570,7 @@
}
if (print_snippet) {
std::vector<std::string> snippet_lines;
- SplitString(result.output_snippet, '\n', &snippet_lines);
+ SplitStringDontTrim(result.output_snippet, '\n', &snippet_lines);
if (snippet_lines.size() > kOutputSnippetLinesLimit) {
size_t truncated_size = snippet_lines.size() - kOutputSnippetLinesLimit;
snippet_lines.erase(
diff --git a/base/test/malloc_wrapper.cc b/base/test/malloc_wrapper.cc
new file mode 100644
index 0000000..eb280a3
--- /dev/null
+++ b/base/test/malloc_wrapper.cc
@@ -0,0 +1,11 @@
+// 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 "malloc_wrapper.h"
+
+#include <stdlib.h>
+
+void* MallocWrapper(size_t size) {
+ return malloc(size);
+}
diff --git a/base/test/malloc_wrapper.h b/base/test/malloc_wrapper.h
new file mode 100644
index 0000000..0fa7dbb
--- /dev/null
+++ b/base/test/malloc_wrapper.h
@@ -0,0 +1,21 @@
+// 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 BASE_TEST_MALLOC_WRAPPER_H_
+#define BASE_TEST_MALLOC_WRAPPER_H_
+
+#include "base/basictypes.h"
+
+// BASE_EXPORT depends on COMPONENT_BUILD.
+// This will always be a separate shared library, so don't use BASE_EXPORT here.
+#if defined(WIN32)
+#define MALLOC_WRAPPER_EXPORT __declspec(dllexport)
+#else
+#define MALLOC_WRAPPER_EXPORT __attribute__((visibility("default")))
+#endif // defined(WIN32)
+
+// Calls malloc directly.
+MALLOC_WRAPPER_EXPORT void* MallocWrapper(size_t size);
+
+#endif // BASE_TEST_MALLOC_WRAPPER_H_
diff --git a/base/test/mock_entropy_provider.cc b/base/test/mock_entropy_provider.cc
new file mode 100644
index 0000000..75186a5
--- /dev/null
+++ b/base/test/mock_entropy_provider.cc
@@ -0,0 +1,16 @@
+// 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/test/mock_entropy_provider.h"
+
+namespace base {
+
+MockEntropyProvider::~MockEntropyProvider() {}
+
+double MockEntropyProvider::GetEntropyForTrial(
+ const std::string& trial_name, uint32 randomization_seed) const {
+ return 0.5;
+}
+
+} // namespace base
diff --git a/base/test/mock_entropy_provider.h b/base/test/mock_entropy_provider.h
new file mode 100644
index 0000000..c55bea6
--- /dev/null
+++ b/base/test/mock_entropy_provider.h
@@ -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.
+
+#ifndef BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
+#define BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
+
+#include "base/metrics/field_trial.h"
+
+namespace base {
+
+class MockEntropyProvider : public base::FieldTrial::EntropyProvider {
+ public:
+ ~MockEntropyProvider() override;
+
+ // base::FieldTrial::EntropyProvider:
+ double GetEntropyForTrial(const std::string& trial_name,
+ uint32 randomization_seed) const override;
+};
+
+} // namespace base
+
+#endif // BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
diff --git a/base/test/sequenced_worker_pool_owner.cc b/base/test/sequenced_worker_pool_owner.cc
index f6a0d01..4486323 100644
--- a/base/test/sequenced_worker_pool_owner.cc
+++ b/base/test/sequenced_worker_pool_owner.cc
@@ -43,6 +43,9 @@
void SequencedWorkerPoolOwner::WillWaitForShutdown() {
if (!will_wait_for_shutdown_callback_.is_null()) {
will_wait_for_shutdown_callback_.Run();
+
+ // Release the reference to the callback to prevent retain cycles.
+ will_wait_for_shutdown_callback_ = Closure();
}
}
diff --git a/base/test/test_discardable_memory_allocator.cc b/base/test/test_discardable_memory_allocator.cc
index cb2cccf..23d529c 100644
--- a/base/test/test_discardable_memory_allocator.cc
+++ b/base/test/test_discardable_memory_allocator.cc
@@ -13,15 +13,15 @@
class DiscardableMemoryImpl : public DiscardableMemory {
public:
- explicit DiscardableMemoryImpl(size_t size) : memory_(new uint8_t[size]) {}
+ explicit DiscardableMemoryImpl(size_t size) : data_(new uint8_t[size]) {}
// Overridden from DiscardableMemory:
bool Lock() override { return false; }
void Unlock() override {}
- void* Memory() const override { return memory_.get(); }
+ void* data() const override { return data_.get(); }
private:
- scoped_ptr<uint8_t[]> memory_;
+ scoped_ptr<uint8_t[]> data_;
};
} // namespace
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index 8cc2e6d..f2e18a3 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -67,15 +67,55 @@
} // namespace
+// TestMockTimeTaskRunner::TestOrderedPendingTask -----------------------------
+
+// Subclass of TestPendingTask which has a strictly monotonically increasing ID
+// for every task, so that tasks posted with the same 'time to run' can be run
+// in the order of being posted.
+struct TestMockTimeTaskRunner::TestOrderedPendingTask
+ : public base::TestPendingTask {
+ TestOrderedPendingTask();
+ TestOrderedPendingTask(const tracked_objects::Location& location,
+ const Closure& task,
+ TimeTicks post_time,
+ TimeDelta delay,
+ size_t ordinal,
+ TestNestability nestability);
+ ~TestOrderedPendingTask();
+
+ size_t ordinal;
+};
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask()
+ : ordinal(0) {
+}
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask(
+ const tracked_objects::Location& location,
+ const Closure& task,
+ TimeTicks post_time,
+ TimeDelta delay,
+ size_t ordinal,
+ TestNestability nestability)
+ : base::TestPendingTask(location, task, post_time, delay, nestability),
+ ordinal(ordinal) {
+}
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::~TestOrderedPendingTask() {
+}
+
// TestMockTimeTaskRunner -----------------------------------------------------
bool TestMockTimeTaskRunner::TemporalOrder::operator()(
- const TestPendingTask& first_task,
- const TestPendingTask& second_task) const {
+ const TestOrderedPendingTask& first_task,
+ const TestOrderedPendingTask& second_task) const {
+ if (first_task.GetTimeToRun() == second_task.GetTimeToRun())
+ return first_task.ordinal > second_task.ordinal;
return first_task.GetTimeToRun() > second_task.GetTimeToRun();
}
-TestMockTimeTaskRunner::TestMockTimeTaskRunner() : now_(Time::UnixEpoch()) {
+TestMockTimeTaskRunner::TestMockTimeTaskRunner()
+ : now_(Time::UnixEpoch()), next_task_ordinal_(0) {
}
TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
@@ -152,8 +192,9 @@
const Closure& task,
TimeDelta delay) {
AutoLock scoped_lock(tasks_lock_);
- tasks_.push(TestPendingTask(from_here, task, now_ticks_, delay,
- TestPendingTask::NESTABLE));
+ tasks_.push(TestOrderedPendingTask(from_here, task, now_ticks_, delay,
+ next_task_ordinal_++,
+ TestPendingTask::NESTABLE));
return true;
}
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 705af10..6319e0c 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -112,15 +112,17 @@
virtual void OnAfterTaskRun();
private:
+ struct TestOrderedPendingTask;
+
// Predicate that defines a strict weak temporal ordering of tasks.
class TemporalOrder {
public:
- bool operator()(const TestPendingTask& first_task,
- const TestPendingTask& second_task) const;
+ bool operator()(const TestOrderedPendingTask& first_task,
+ const TestOrderedPendingTask& second_task) const;
};
- typedef std::priority_queue<TestPendingTask,
- std::vector<TestPendingTask>,
+ typedef std::priority_queue<TestOrderedPendingTask,
+ std::vector<TestOrderedPendingTask>,
TemporalOrder> TaskPriorityQueue;
// Core of the implementation for all flavors of fast-forward methods. Given a
@@ -148,6 +150,11 @@
// Temporally ordered heap of pending tasks. Must only be accessed while the
// |tasks_lock_| is held.
TaskPriorityQueue tasks_;
+
+ // The ordinal to use for the next task. Must only be accessed while the
+ // |tasks_lock_| is held.
+ size_t next_task_ordinal_;
+
Lock tasks_lock_;
DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
diff --git a/base/test/test_reg_util_win_unittest.cc b/base/test/test_reg_util_win_unittest.cc
index 11abe5d..216d58e 100644
--- a/base/test/test_reg_util_win_unittest.cc
+++ b/base/test/test_reg_util_win_unittest.cc
@@ -32,7 +32,7 @@
key.DeleteKey(kTestKeyPath);
}
- virtual ~RegistryOverrideManagerTest() {
+ ~RegistryOverrideManagerTest() override {
base::win::RegKey key(HKEY_CURRENT_USER);
key.DeleteKey(fake_test_key_root_.c_str());
}
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index d40dd98..ee135e5 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -55,7 +55,7 @@
class MaybeTestDisabler : public testing::EmptyTestEventListener {
public:
- virtual void OnTestStart(const testing::TestInfo& test_info) override {
+ void OnTestStart(const testing::TestInfo& test_info) override {
ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info))
<< "Probably the OS #ifdefs don't include all of the necessary "
"platforms.\nPlease ensure that no tests have the MAYBE_ prefix "
@@ -69,11 +69,11 @@
: old_command_line_(base::CommandLine::NO_PROGRAM) {
}
- virtual void OnTestStart(const testing::TestInfo& test_info) override {
+ void OnTestStart(const testing::TestInfo& test_info) override {
old_command_line_ = *base::CommandLine::ForCurrentProcess();
}
- virtual void OnTestEnd(const testing::TestInfo& test_info) override {
+ void OnTestEnd(const testing::TestInfo& test_info) override {
*base::CommandLine::ForCurrentProcess() = old_command_line_;
}
diff --git a/base/test/user_action_tester.cc b/base/test/user_action_tester.cc
new file mode 100644
index 0000000..3fdab12
--- /dev/null
+++ b/base/test/user_action_tester.cc
@@ -0,0 +1,35 @@
+// 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/test/user_action_tester.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+
+namespace base {
+
+UserActionTester::UserActionTester()
+ : action_callback_(
+ base::Bind(&UserActionTester::OnUserAction, base::Unretained(this))) {
+ base::AddActionCallback(action_callback_);
+}
+
+UserActionTester::~UserActionTester() {
+ base::RemoveActionCallback(action_callback_);
+}
+
+int UserActionTester::GetActionCount(const std::string& user_action) const {
+ UserActionCountMap::const_iterator iter = count_map_.find(user_action);
+ return iter == count_map_.end() ? 0 : iter->second;
+}
+
+void UserActionTester::ResetCounts() {
+ count_map_.clear();
+}
+
+void UserActionTester::OnUserAction(const std::string& user_action) {
+ ++(count_map_[user_action]);
+}
+
+} // namespace base
diff --git a/base/test/user_action_tester.h b/base/test/user_action_tester.h
new file mode 100644
index 0000000..6b0efc5
--- /dev/null
+++ b/base/test/user_action_tester.h
@@ -0,0 +1,46 @@
+// 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 BASE_TEST_USER_ACTION_TESTER_H_
+#define BASE_TEST_USER_ACTION_TESTER_H_
+
+#include <map>
+#include <string>
+
+#include "base/metrics/user_metrics.h"
+
+namespace base {
+
+// This class observes and collects user action notifications that are sent
+// by the tests, so that they can be examined afterwards for correctness.
+// Note: This class is NOT thread-safe.
+class UserActionTester {
+ public:
+ UserActionTester();
+ ~UserActionTester();
+
+ // Returns the number of times the given |user_action| occurred.
+ int GetActionCount(const std::string& user_action) const;
+
+ // Resets all user action counts to 0.
+ void ResetCounts();
+
+ private:
+ typedef std::map<std::string, int> UserActionCountMap;
+
+ // The callback that is notified when a user actions occurs.
+ void OnUserAction(const std::string& user_action);
+
+ // A map that tracks the number of times a user action has occurred.
+ UserActionCountMap count_map_;
+
+ // The callback that is added to the global action callback list.
+ base::ActionCallback action_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserActionTester);
+};
+
+} // namespace base
+
+#endif // BASE_TEST_USER_ACTION_TESTER_H_
diff --git a/base/test/user_action_tester_unittest.cc b/base/test/user_action_tester_unittest.cc
new file mode 100644
index 0000000..a51849f
--- /dev/null
+++ b/base/test/user_action_tester_unittest.cc
@@ -0,0 +1,86 @@
+// 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/test/user_action_tester.h"
+
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+const char kUserAction1[] = "user.action.1";
+const char kUserAction2[] = "user.action.2";
+const char kUserAction3[] = "user.action.3";
+
+// Record an action and cause all ActionCallback observers to be notified.
+void RecordAction(const char user_action[]) {
+ base::RecordAction(base::UserMetricsAction(user_action));
+}
+
+} // namespace
+
+// Verify user action counts are zero initially.
+TEST(UserActionTesterTest, GetActionCountWhenNoActionsHaveBeenRecorded) {
+ UserActionTester user_action_tester;
+ EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
+}
+
+// Verify user action counts are tracked properly.
+TEST(UserActionTesterTest, GetActionCountWhenActionsHaveBeenRecorded) {
+ UserActionTester user_action_tester;
+
+ RecordAction(kUserAction1);
+ RecordAction(kUserAction2);
+ RecordAction(kUserAction2);
+
+ EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+ EXPECT_EQ(2, user_action_tester.GetActionCount(kUserAction2));
+ EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
+}
+
+// Verify no seg faults occur when resetting action counts when none have been
+// recorded.
+TEST(UserActionTesterTest, ResetCountsWhenNoActionsHaveBeenRecorded) {
+ UserActionTester user_action_tester;
+ user_action_tester.ResetCounts();
+}
+
+// Verify user action counts are set to zero on a ResetCounts.
+TEST(UserActionTesterTest, ResetCountsWhenActionsHaveBeenRecorded) {
+ UserActionTester user_action_tester;
+
+ RecordAction(kUserAction1);
+ RecordAction(kUserAction1);
+ RecordAction(kUserAction2);
+ user_action_tester.ResetCounts();
+
+ EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
+ EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction2));
+ EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
+}
+
+// Verify the UserActionsTester is notified when base::RecordAction is called.
+TEST(UserActionTesterTest, VerifyUserActionTesterListensForUserActions) {
+ UserActionTester user_action_tester;
+
+ base::RecordAction(base::UserMetricsAction(kUserAction1));
+
+ EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+}
+
+// Verify the UserActionsTester is notified when base::RecordComputedAction is
+// called.
+TEST(UserActionTesterTest,
+ VerifyUserActionTesterListensForComputedUserActions) {
+ UserActionTester user_action_tester;
+
+ base::RecordComputedAction(kUserAction1);
+
+ EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+}
+
+} // namespace base
diff --git a/base/third_party/nspr/BUILD.gn b/base/third_party/nspr/BUILD.gn
deleted file mode 100644
index 034f37b..0000000
--- a/base/third_party/nspr/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("nspr") {
- visibility = [ "//base/*" ]
-
- sources = [
- "prtime.cc",
- "prtime.h",
- ]
-
- # In GYP this project is part of base, so it uses the base implementation
- # define. TODO(brettw) rename this define.
- configs += [ "//base:base_implementation" ]
-
- if (is_android && !is_debug) {
- configs -= [ "//build/config/compiler:optimize" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
-}
diff --git a/base/third_party/xdg_mime/README.chromium b/base/third_party/xdg_mime/README.chromium
index 29d239a..95f3a96 100644
--- a/base/third_party/xdg_mime/README.chromium
+++ b/base/third_party/xdg_mime/README.chromium
@@ -7,5 +7,7 @@
@ 2cdd8d36d7930d5a594587286cb1949ff62f7027 on 2012/08/06.
In addition, we have the following patch(es):
-- compile.patch: small tweaks to make the code compile.
-- Added a LICENSE file.
+ - compile.patch: small tweaks to make the code compile.
+ - free_pointer_later.patch: small patch that fixes potential crash in
+ xdg_mime_get_mime_type_for_file() - use of pointer after being freed.
+ - Added a LICENSE file.
diff --git a/base/third_party/xdg_mime/free_pointer_later.patch b/base/third_party/xdg_mime/free_pointer_later.patch
new file mode 100644
index 0000000..7668761
--- /dev/null
+++ b/base/third_party/xdg_mime/free_pointer_later.patch
@@ -0,0 +1,22 @@
+diff --git a/base/third_party/xdg_mime/xdgmime.c b/base/third_party/xdg_mime/xdgmime.c
+index c7b16bb..6dc58c2 100644
+--- a/base/third_party/xdg_mime/xdgmime.c
++++ b/base/third_party/xdg_mime/xdgmime.c
+@@ -558,13 +558,13 @@ xdg_mime_get_mime_type_for_file (const char *file_name,
+ mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, NULL,
+ mime_types, n);
+
+- free (data);
+ fclose (file);
+
+- if (mime_type)
+- return mime_type;
++ if (!mime_type)
++ mime_type = _xdg_binary_or_text_fallback(data, bytes_read);
+
+- return _xdg_binary_or_text_fallback(data, bytes_read);
++ free (data);
++ return mime_type;
+ }
+
+ const char *
diff --git a/base/third_party/xdg_mime/xdgmime.c b/base/third_party/xdg_mime/xdgmime.c
index c7b16bb..6dc58c2 100644
--- a/base/third_party/xdg_mime/xdgmime.c
+++ b/base/third_party/xdg_mime/xdgmime.c
@@ -558,13 +558,13 @@
mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, NULL,
mime_types, n);
- free (data);
fclose (file);
- if (mime_type)
- return mime_type;
+ if (!mime_type)
+ mime_type = _xdg_binary_or_text_fallback(data, bytes_read);
- return _xdg_binary_or_text_fallback(data, bytes_read);
+ free (data);
+ return mime_type;
}
const char *
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
index 2874314..653961d 100644
--- a/base/threading/platform_thread.h
+++ b/base/threading/platform_thread.h
@@ -110,15 +110,17 @@
const PlatformThreadId kInvalidThreadId(0);
-// Valid values for SetThreadPriority()
-enum ThreadPriority{
- kThreadPriority_Normal,
- // Suitable for low-latency, glitch-resistant audio.
- kThreadPriority_RealtimeAudio,
- // Suitable for threads which generate data for the display (at ~60Hz).
- kThreadPriority_Display,
+// Valid values for SetThreadPriority(), listed in increasing order of
+// importance.
+enum class ThreadPriority {
// Suitable for threads that shouldn't disrupt high priority work.
- kThreadPriority_Background
+ BACKGROUND,
+ // Default priority level.
+ NORMAL,
+ // Suitable for threads which generate data for the display (at ~60Hz).
+ DISPLAY,
+ // Suitable for low-latency, glitch-resistant audio.
+ REALTIME_AUDIO,
};
// A namespace for low-level thread functions.
@@ -141,7 +143,10 @@
// we're on the right thread quickly.
static PlatformThreadRef CurrentRef();
- // Get the current handle.
+ // Get the handle representing the current thread. On Windows, this is a
+ // pseudo handle constant which will always represent the thread using it and
+ // hence should not be shared with other threads nor be used to differentiate
+ // the current thread from another.
static PlatformThreadHandle CurrentHandle();
// Yield the current thread so another thread can be scheduled.
@@ -171,9 +176,7 @@
// CreateWithPriority() does the same thing as Create() except the priority of
// the thread is set based on |priority|. Can be used in place of Create()
- // followed by SetThreadPriority(). SetThreadPriority() has not been
- // implemented on the Linux platform yet, this is the only way to get a high
- // priority thread on Linux.
+ // followed by SetThreadPriority().
static bool CreateWithPriority(size_t stack_size, Delegate* delegate,
PlatformThreadHandle* thread_handle,
ThreadPriority priority);
@@ -191,6 +194,8 @@
static void SetThreadPriority(PlatformThreadHandle handle,
ThreadPriority priority);
+ static ThreadPriority GetThreadPriority(PlatformThreadHandle handle);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
};
diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
index aab4c19..a31f659 100644
--- a/base/threading/platform_thread_android.cc
+++ b/base/threading/platform_thread_android.cc
@@ -38,17 +38,17 @@
// We use -6 for display, but we may want to split this into urgent (-8) and
// non-urgent (-4).
const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
- {kThreadPriority_RealtimeAudio, -16},
- {kThreadPriority_Background, 10},
- {kThreadPriority_Normal, 0},
- {kThreadPriority_Display, -6},
+ {ThreadPriority::BACKGROUND, 10},
+ {ThreadPriority::NORMAL, 0},
+ {ThreadPriority::DISPLAY, -6},
+ {ThreadPriority::REALTIME_AUDIO, -16},
};
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
- ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority priority) {
// On Android, we set the Audio priority through JNI as Audio priority
// will also allow the process to run while it is backgrounded.
- if (priority == kThreadPriority_RealtimeAudio) {
+ if (priority == ThreadPriority::REALTIME_AUDIO) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId());
return true;
@@ -56,6 +56,12 @@
return false;
}
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority* priority) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
} // namespace internal
void PlatformThread::SetName(const char* name) {
@@ -83,7 +89,7 @@
// Threads on linux/android may inherit their priority from the thread
// where they were created. This sets all new threads to the default.
PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(),
- kThreadPriority_Normal);
+ ThreadPriority::NORMAL);
}
void TerminateOnThread() {
diff --git a/base/threading/platform_thread_freebsd.cc b/base/threading/platform_thread_freebsd.cc
index a163f65..7ba4eed 100644
--- a/base/threading/platform_thread_freebsd.cc
+++ b/base/threading/platform_thread_freebsd.cc
@@ -30,22 +30,42 @@
} // namespace
const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
- { kThreadPriority_RealtimeAudio, -10 },
- { kThreadPriority_Background, 10 },
- { kThreadPriority_Normal, 0 },
- { kThreadPriority_Display, -6 },
+ {ThreadPriority::BACKGROUND, 10},
+ {ThreadPriority::NORMAL, 0},
+ {ThreadPriority::DISPLAY, -6},
+ {ThreadPriority::REALTIME_AUDIO, -10},
}
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
- ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority priority) {
#if !defined(OS_NACL)
- return priority == kThreadPriority_RealtimeAudio &&
+ // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+ // of |handle|. http://crbug.com/468793.
+ return priority == ThreadPriority::REALTIME_AUDIO &&
pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0;
#else
return false;
#endif
}
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority* priority) {
+#if !defined(OS_NACL)
+ // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+ // of |handle|. http://crbug.com/468793.
+ int maybe_sched_rr = 0;
+ struct sched_param maybe_realtime_prio = {0};
+ if (pthread_getschedparam(pthread_self(), &maybe_sched_rr,
+ &maybe_realtime_prio) == 0 &&
+ maybe_sched_rr == SCHED_RR &&
+ maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) {
+ *priority = ThreadPriority::REALTIME_AUDIO;
+ return true;
+ }
+#endif
+ return false;
+}
+
} // namespace internal
// static
diff --git a/base/threading/platform_thread_internal_posix.cc b/base/threading/platform_thread_internal_posix.cc
index 7e6604b..9af0204 100644
--- a/base/threading/platform_thread_internal_posix.cc
+++ b/base/threading/platform_thread_internal_posix.cc
@@ -20,6 +20,16 @@
return 0;
}
+ThreadPriority NiceValueToThreadPriority(int nice_value) {
+ for (const ThreadPriorityToNiceValuePair& pair :
+ kThreadPriorityToNiceValueMap) {
+ if (pair.nice_value == nice_value)
+ return pair.priority;
+ }
+ NOTREACHED() << "Unknown nice value";
+ return ThreadPriority::NORMAL;
+}
+
} // namespace internal
} // namespace base
diff --git a/base/threading/platform_thread_internal_posix.h b/base/threading/platform_thread_internal_posix.h
index 1ae968f..62006ce 100644
--- a/base/threading/platform_thread_internal_posix.h
+++ b/base/threading/platform_thread_internal_posix.h
@@ -21,12 +21,22 @@
// implementation of kThreadPriorityToNiceValueMap.
int ThreadPriorityToNiceValue(ThreadPriority priority);
+// Returns the ThreadPrioirty matching |nice_value| based on the platform-
+// specific implementation of kThreadPriorityToNiceValueMap.
+ThreadPriority NiceValueToThreadPriority(int nice_value);
+
// Allows platform specific tweaks to the generic POSIX solution for
// SetThreadPriority. Returns true if the platform-specific implementation
// handled this |priority| change, false if the generic implementation should
// instead proceed.
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
- ThreadPriority priority);
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority priority);
+
+// Returns true if there is a platform-specific ThreadPriority set on |handle|
+// (and returns the actual ThreadPriority via |priority|). Returns false
+// otherwise, leaving |priority| untouched.
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority* priority);
} // namespace internal
diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc
index 623a3de..b72fb5b 100644
--- a/base/threading/platform_thread_linux.cc
+++ b/base/threading/platform_thread_linux.cc
@@ -31,22 +31,42 @@
} // namespace
const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
- {kThreadPriority_RealtimeAudio, -10},
- {kThreadPriority_Background, 10},
- {kThreadPriority_Normal, 0},
- {kThreadPriority_Display, -6},
+ {ThreadPriority::BACKGROUND, 10},
+ {ThreadPriority::NORMAL, 0},
+ {ThreadPriority::DISPLAY, -6},
+ {ThreadPriority::REALTIME_AUDIO, -10},
};
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
- ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority priority) {
#if !defined(OS_NACL)
- return priority == kThreadPriority_RealtimeAudio &&
+ // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+ // of |handle|. http://crbug.com/468793.
+ return priority == ThreadPriority::REALTIME_AUDIO &&
pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0;
#else
return false;
#endif
}
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+ ThreadPriority* priority) {
+#if !defined(OS_NACL)
+ int maybe_sched_rr = 0;
+ struct sched_param maybe_realtime_prio = {0};
+ // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+ // of |handle|. http://crbug.com/468793.
+ if (pthread_getschedparam(pthread_self(), &maybe_sched_rr,
+ &maybe_realtime_prio) == 0 &&
+ maybe_sched_rr == SCHED_RR &&
+ maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) {
+ *priority = ThreadPriority::REALTIME_AUDIO;
+ return true;
+ }
+#endif
+ return false;
+}
+
} // namespace internal
// static
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm
index 147e625..fd40d79 100644
--- a/base/threading/platform_thread_mac.mm
+++ b/base/threading/platform_thread_mac.mm
@@ -161,10 +161,10 @@
mach_port_t mach_thread_id = pthread_mach_thread_np(handle.handle_);
switch (priority) {
- case kThreadPriority_Normal:
+ case ThreadPriority::NORMAL:
SetPriorityNormal(mach_thread_id);
break;
- case kThreadPriority_RealtimeAudio:
+ case ThreadPriority::REALTIME_AUDIO:
SetPriorityRealtimeAudio(mach_thread_id);
break;
default:
@@ -173,6 +173,12 @@
}
}
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+ NOTIMPLEMENTED();
+ return ThreadPriority::NORMAL;
+}
+
size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
#if defined(OS_IOS)
return 0;
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
index 5c5023b..3dbdc98 100644
--- a/base/threading/platform_thread_posix.cc
+++ b/base/threading/platform_thread_posix.cc
@@ -39,7 +39,7 @@
ThreadParams()
: delegate(NULL),
joinable(false),
- priority(kThreadPriority_Normal),
+ priority(ThreadPriority::NORMAL),
handle(NULL),
handle_set(false, false) {
}
@@ -59,7 +59,7 @@
if (!thread_params->joinable)
base::ThreadRestrictions::SetSingletonAllowed(false);
- if (thread_params->priority != kThreadPriority_Normal) {
+ if (thread_params->priority != ThreadPriority::NORMAL) {
PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(),
thread_params->priority);
}
@@ -201,7 +201,7 @@
PlatformThreadHandle* thread_handle) {
base::ThreadRestrictions::ScopedAllowWait allow_wait;
return CreateThread(stack_size, true /* joinable thread */,
- delegate, thread_handle, kThreadPriority_Normal);
+ delegate, thread_handle, ThreadPriority::NORMAL);
}
// static
@@ -219,7 +219,7 @@
base::ThreadRestrictions::ScopedAllowWait allow_wait;
bool result = CreateThread(stack_size, false /* non-joinable thread */,
- delegate, &unused, kThreadPriority_Normal);
+ delegate, &unused, ThreadPriority::NORMAL);
return result;
}
@@ -232,13 +232,16 @@
CHECK_EQ(0, pthread_join(thread_handle.handle_, NULL));
}
-// Mac has its own SetThreadPriority() implementation.
+// Mac has its own Set/GetThreadPriority() implementations.
#if !defined(OS_MACOSX)
+
// static
void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
ThreadPriority priority) {
-#if !defined(OS_NACL)
- if (internal::HandleSetThreadPriorityForPlatform(handle, priority))
+#if defined(OS_NACL)
+ NOTIMPLEMENTED();
+#else
+ if (internal::SetThreadPriorityForPlatform(handle, priority))
return;
// setpriority(2) should change the whole thread group's (i.e. process)
@@ -255,8 +258,38 @@
DVPLOG(1) << "Failed to set nice value of thread (" << handle.id_ << ") to "
<< nice_setting;
}
+#endif // defined(OS_NACL)
+}
+
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+#if defined(OS_NACL)
+ NOTIMPLEMENTED();
+ return ThreadPriority::NORMAL;
+#else
+ // Mirrors SetThreadPriority()'s implementation.
+ ThreadPriority platform_specific_priority;
+ if (internal::GetThreadPriorityForPlatform(handle,
+ &platform_specific_priority)) {
+ return platform_specific_priority;
+ }
+
+ DCHECK_NE(handle.id_, kInvalidThreadId);
+ const PlatformThreadId current_id = PlatformThread::CurrentId();
+ // Need to clear errno before calling getpriority():
+ // http://man7.org/linux/man-pages/man2/getpriority.2.html
+ errno = 0;
+ int nice_value =
+ getpriority(PRIO_PROCESS, handle.id_ == current_id ? 0 : handle.id_);
+ if (errno != 0) {
+ DVPLOG(1) << "Failed to get nice value of thread (" << handle.id_ << ")";
+ return ThreadPriority::NORMAL;
+ }
+
+ return internal::NiceValueToThreadPriority(nice_value);
#endif // !defined(OS_NACL)
}
+
#endif // !defined(OS_MACOSX)
} // namespace base
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
index 21260e5..c4b3d5d 100644
--- a/base/threading/platform_thread_unittest.cc
+++ b/base/threading/platform_thread_unittest.cc
@@ -3,10 +3,15 @@
// found in the LICENSE file.
#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
-
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
namespace base {
// Trivial tests that thread runs and doesn't crash on create and join ---------
@@ -51,26 +56,59 @@
// Tests of basic thread functions ---------------------------------------------
-class FunctionTestThread : public TrivialThread {
+class FunctionTestThread : public PlatformThread::Delegate {
public:
- FunctionTestThread() : thread_id_(0) {}
+ FunctionTestThread()
+ : thread_id_(kInvalidThreadId),
+ thread_started_(true, false),
+ terminate_thread_(true, false),
+ done_(false) {}
+ ~FunctionTestThread() override {
+ EXPECT_TRUE(terminate_thread_.IsSignaled())
+ << "Need to mark thread for termination and join the underlying thread "
+ << "before destroying a FunctionTestThread as it owns the "
+ << "WaitableEvent blocking the underlying thread's main.";
+ }
+ // Grabs |thread_id_|, signals |thread_started_|, and then waits for
+ // |terminate_thread_| to be signaled before exiting.
void ThreadMain() override {
thread_id_ = PlatformThread::CurrentId();
- PlatformThread::YieldCurrentThread();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
+ EXPECT_NE(thread_id_, kInvalidThreadId);
// Make sure that the thread ID is the same across calls.
EXPECT_EQ(thread_id_, PlatformThread::CurrentId());
- TrivialThread::ThreadMain();
+ thread_started_.Signal();
+
+ terminate_thread_.Wait();
+
+ done_ = true;
}
- PlatformThreadId thread_id() const { return thread_id_; }
+ PlatformThreadId thread_id() const {
+ EXPECT_TRUE(thread_started_.IsSignaled()) << "Thread ID still unknown";
+ return thread_id_;
+ }
+
+ bool IsRunning() const {
+ return thread_started_.IsSignaled() && !done_;
+ }
+
+ // Blocks until this thread is started.
+ void WaitForThreadStart() { thread_started_.Wait(); }
+
+ // Mark this thread for termination (callers must then join this thread to be
+ // guaranteed of termination).
+ void MarkForTermination() { terminate_thread_.Signal(); }
private:
PlatformThreadId thread_id_;
+ mutable WaitableEvent thread_started_;
+ WaitableEvent terminate_thread_;
+ bool done_;
+
DISALLOW_COPY_AND_ASSIGN(FunctionTestThread);
};
@@ -80,12 +118,16 @@
FunctionTestThread thread;
PlatformThreadHandle handle;
- ASSERT_FALSE(thread.did_run());
+ ASSERT_FALSE(thread.IsRunning());
ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
- PlatformThread::Join(handle);
- ASSERT_TRUE(thread.did_run());
+ thread.WaitForThreadStart();
+ ASSERT_TRUE(thread.IsRunning());
EXPECT_NE(thread.thread_id(), main_thread_id);
+ thread.MarkForTermination();
+ PlatformThread::Join(handle);
+ ASSERT_FALSE(thread.IsRunning());
+
// Make sure that the thread ID is the same across calls.
EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
}
@@ -97,13 +139,15 @@
PlatformThreadHandle handle[arraysize(thread)];
for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_FALSE(thread[n].did_run());
+ ASSERT_FALSE(thread[n].IsRunning());
+
for (size_t n = 0; n < arraysize(thread); n++)
ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
for (size_t n = 0; n < arraysize(thread); n++)
- PlatformThread::Join(handle[n]);
+ thread[n].WaitForThreadStart();
+
for (size_t n = 0; n < arraysize(thread); n++) {
- ASSERT_TRUE(thread[n].did_run());
+ ASSERT_TRUE(thread[n].IsRunning());
EXPECT_NE(thread[n].thread_id(), main_thread_id);
// Make sure no two threads get the same ID.
@@ -112,8 +156,120 @@
}
}
+ for (size_t n = 0; n < arraysize(thread); n++)
+ thread[n].MarkForTermination();
+ for (size_t n = 0; n < arraysize(thread); n++)
+ PlatformThread::Join(handle[n]);
+ for (size_t n = 0; n < arraysize(thread); n++)
+ ASSERT_FALSE(thread[n].IsRunning());
+
// Make sure that the thread ID is the same across calls.
EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
}
+namespace {
+
+const ThreadPriority kThreadPriorityTestValues[] = {
+// Disable non-normal priority toggling on POSIX as it appears to be broken
+// (http://crbug.com/468793). This is prefered to disabling the tests altogether
+// on POSIX as it at least provides coverage for running this code under
+// "normal" priority.
+#if !defined(OS_POSIX)
+ ThreadPriority::DISPLAY,
+ ThreadPriority::REALTIME_AUDIO,
+ // Keep BACKGROUND second to last to test backgrounding from other
+ // priorities.
+ ThreadPriority::BACKGROUND,
+#endif // !defined(OS_POSIX)
+ // Keep NORMAL last to test unbackgrounding.
+ ThreadPriority::NORMAL
+};
+
+} // namespace
+
+// Test changing another thread's priority.
+// NOTE: This test is partially disabled on POSIX, see note above and
+// http://crbug.com/468793.
+TEST(PlatformThreadTest, ThreadPriorityOtherThread) {
+ PlatformThreadHandle current_handle(PlatformThread::CurrentHandle());
+
+ // Confirm that the current thread's priority is as expected.
+ EXPECT_EQ(ThreadPriority::NORMAL,
+ PlatformThread::GetThreadPriority(current_handle));
+
+ // Create a test thread.
+ FunctionTestThread thread;
+ PlatformThreadHandle handle;
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+ thread.WaitForThreadStart();
+ EXPECT_NE(thread.thread_id(), kInvalidThreadId);
+ EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId());
+
+ // New threads should get normal priority by default.
+ EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle));
+
+ // Toggle each supported priority on the test thread and confirm it only
+ // affects it (and not the current thread).
+ for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
+ SCOPED_TRACE(i);
+
+ // Alter and verify the test thread's priority.
+ PlatformThread::SetThreadPriority(handle, kThreadPriorityTestValues[i]);
+ EXPECT_EQ(kThreadPriorityTestValues[i],
+ PlatformThread::GetThreadPriority(handle));
+
+ // Make sure the current thread was otherwise unaffected.
+ EXPECT_EQ(ThreadPriority::NORMAL,
+ PlatformThread::GetThreadPriority(current_handle));
+ }
+
+ thread.MarkForTermination();
+ PlatformThread::Join(handle);
+}
+
+// Test changing the current thread's priority (which has different semantics on
+// some platforms).
+// NOTE: This test is partially disabled on POSIX, see note above and
+// http://crbug.com/468793.
+TEST(PlatformThreadTest, ThreadPriorityCurrentThread) {
+ PlatformThreadHandle current_handle(PlatformThread::CurrentHandle());
+
+ // Confirm that the current thread's priority is as expected.
+ EXPECT_EQ(ThreadPriority::NORMAL,
+ PlatformThread::GetThreadPriority(current_handle));
+
+ // Create a test thread for verification purposes only.
+ FunctionTestThread thread;
+ PlatformThreadHandle handle;
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+ thread.WaitForThreadStart();
+ EXPECT_NE(thread.thread_id(), kInvalidThreadId);
+ EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId());
+
+ // Confirm that the new thread's priority is as expected.
+ EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle));
+
+ // Toggle each supported priority on the current thread and confirm it only
+ // affects it (and not the test thread).
+ for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
+ SCOPED_TRACE(i);
+
+ // Alter and verify the current thread's priority.
+ PlatformThread::SetThreadPriority(current_handle,
+ kThreadPriorityTestValues[i]);
+ EXPECT_EQ(kThreadPriorityTestValues[i],
+ PlatformThread::GetThreadPriority(current_handle));
+
+ // Make sure the test thread was otherwise unaffected.
+ EXPECT_EQ(ThreadPriority::NORMAL,
+ PlatformThread::GetThreadPriority(handle));
+ }
+
+ // Restore current thread priority for follow-up tests.
+ PlatformThread::SetThreadPriority(current_handle, ThreadPriority::NORMAL);
+
+ thread.MarkForTermination();
+ PlatformThread::Join(handle);
+}
+
} // namespace base
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc
index 3df3719..b9f7a56 100644
--- a/base/threading/platform_thread_win.cc
+++ b/base/threading/platform_thread_win.cc
@@ -126,18 +126,17 @@
// static
PlatformThreadId PlatformThread::CurrentId() {
- return GetCurrentThreadId();
+ return ::GetCurrentThreadId();
}
// static
PlatformThreadRef PlatformThread::CurrentRef() {
- return PlatformThreadRef(GetCurrentThreadId());
+ return PlatformThreadRef(::GetCurrentThreadId());
}
// static
PlatformThreadHandle PlatformThread::CurrentHandle() {
- NOTIMPLEMENTED(); // See OpenThread()
- return PlatformThreadHandle();
+ return PlatformThreadHandle(::GetCurrentThread());
}
// static
@@ -234,17 +233,56 @@
// static
void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
ThreadPriority priority) {
+ DCHECK(!handle.is_null());
+
+ int desired_priority = THREAD_PRIORITY_ERROR_RETURN;
switch (priority) {
- case kThreadPriority_Normal:
- ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_NORMAL);
+ case ThreadPriority::BACKGROUND:
+ desired_priority = THREAD_PRIORITY_LOWEST;
break;
- case kThreadPriority_RealtimeAudio:
- ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_TIME_CRITICAL);
+ case ThreadPriority::NORMAL:
+ desired_priority = THREAD_PRIORITY_NORMAL;
+ break;
+ case ThreadPriority::DISPLAY:
+ desired_priority = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case ThreadPriority::REALTIME_AUDIO:
+ desired_priority = THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
NOTREACHED() << "Unknown priority.";
break;
}
+ DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN);
+
+#ifndef NDEBUG
+ const BOOL success =
+#endif
+ ::SetThreadPriority(handle.handle_, desired_priority);
+ DPLOG_IF(ERROR, !success) << "Failed to set thread priority to "
+ << desired_priority;
+}
+
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+ DCHECK(!handle.is_null());
+
+ int priority = ::GetThreadPriority(handle.handle_);
+ switch (priority) {
+ case THREAD_PRIORITY_LOWEST:
+ return ThreadPriority::BACKGROUND;
+ case THREAD_PRIORITY_NORMAL:
+ return ThreadPriority::NORMAL;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ return ThreadPriority::DISPLAY;
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ return ThreadPriority::REALTIME_AUDIO;
+ case THREAD_PRIORITY_ERROR_RETURN:
+ DPCHECK(false) << "GetThreadPriority error"; // Falls through.
+ default:
+ NOTREACHED() << "Unexpected priority: " << priority;
+ return ThreadPriority::NORMAL;
+ }
}
} // namespace base
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 52b178b..6f4a248 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -239,24 +239,41 @@
// SimpleThread implementation. This actually runs the background thread.
void Run() override;
+ // Indicates that a task is about to be run. The parameters provide
+ // additional metainformation about the task being run.
void set_running_task_info(SequenceToken token,
WorkerShutdown shutdown_behavior) {
- running_sequence_ = token;
- running_shutdown_behavior_ = shutdown_behavior;
+ is_processing_task_ = true;
+ task_sequence_token_ = token;
+ task_shutdown_behavior_ = shutdown_behavior;
}
- SequenceToken running_sequence() const {
- return running_sequence_;
+ // Indicates that the task has finished running.
+ void reset_running_task_info() { is_processing_task_ = false; }
+
+ // Whether the worker is processing a task.
+ bool is_processing_task() { return is_processing_task_; }
+
+ SequenceToken task_sequence_token() const {
+ DCHECK(is_processing_task_);
+ return task_sequence_token_;
}
- WorkerShutdown running_shutdown_behavior() const {
- return running_shutdown_behavior_;
+ WorkerShutdown task_shutdown_behavior() const {
+ DCHECK(is_processing_task_);
+ return task_shutdown_behavior_;
}
private:
scoped_refptr<SequencedWorkerPool> worker_pool_;
- SequenceToken running_sequence_;
- WorkerShutdown running_shutdown_behavior_;
+ // The sequence token of the task being processed. Only valid when
+ // is_processing_task_ is true.
+ SequenceToken task_sequence_token_;
+ // The shutdown behavior of the task being processed. Only valid when
+ // is_processing_task_ is true.
+ WorkerShutdown task_shutdown_behavior_;
+ // Whether the Worker is processing a task.
+ bool is_processing_task_;
DISALLOW_COPY_AND_ASSIGN(Worker);
};
@@ -326,11 +343,6 @@
// Called from within the lock, this returns the next sequence task number.
int64 LockedGetNextSequenceTaskNumber();
- // Called from within the lock, returns the shutdown behavior of the task
- // running on the currently executing worker thread. If invoked from a thread
- // that is not one of the workers, returns CONTINUE_ON_SHUTDOWN.
- WorkerShutdown LockedCurrentThreadShutdownBehavior() const;
-
// Gets new task. There are 3 cases depending on the return value:
//
// 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should
@@ -483,7 +495,8 @@
const std::string& prefix)
: SimpleThread(prefix + StringPrintf("Worker%d", thread_number)),
worker_pool_(worker_pool),
- running_shutdown_behavior_(CONTINUE_ON_SHUTDOWN) {
+ task_shutdown_behavior_(BLOCK_SHUTDOWN),
+ is_processing_task_(false) {
Start();
}
@@ -497,7 +510,7 @@
// Store a pointer to the running sequence in thread local storage for
// static function access.
- g_lazy_tls_ptr.Get().Set(&running_sequence_);
+ g_lazy_tls_ptr.Get().Set(&task_sequence_token_);
// Just jump back to the Inner object to run the thread, since it has all the
// tracking information and queues. It might be more natural to implement
@@ -583,10 +596,19 @@
{
AutoLock lock(lock_);
if (shutdown_called_) {
- if (shutdown_behavior != BLOCK_SHUTDOWN ||
- LockedCurrentThreadShutdownBehavior() == CONTINUE_ON_SHUTDOWN) {
+ // Don't allow a new task to be posted if it doesn't block shutdown.
+ if (shutdown_behavior != BLOCK_SHUTDOWN)
+ return false;
+
+ // If the current thread is running a task, and that task doesn't block
+ // shutdown, then it shouldn't be allowed to post any more tasks.
+ ThreadMap::const_iterator found =
+ threads_.find(PlatformThread::CurrentId());
+ if (found != threads_.end() && found->second->is_processing_task() &&
+ found->second->task_shutdown_behavior() != BLOCK_SHUTDOWN) {
return false;
}
+
if (max_blocking_tasks_after_shutdown_ <= 0) {
DLOG(WARNING) << "BLOCK_SHUTDOWN task disallowed";
return false;
@@ -635,7 +657,8 @@
ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
if (found == threads_.end())
return false;
- return sequence_token.Equals(found->second->running_sequence());
+ return found->second->is_processing_task() &&
+ sequence_token.Equals(found->second->task_sequence_token());
}
// See https://code.google.com/p/chromium/issues/detail?id=168415
@@ -765,13 +788,12 @@
// Make sure our task is erased outside the lock for the
// same reason we do this with delete_these_oustide_lock.
- // Also, do it before calling set_running_task_info() so
+ // Also, do it before calling reset_running_task_info() so
// that sequence-checking from within the task's destructor
// still works.
task.task = Closure();
- this_worker->set_running_task_info(
- SequenceToken(), CONTINUE_ON_SHUTDOWN);
+ this_worker->reset_running_task_info();
}
DidRunWorkerTask(task); // Must be done inside the lock.
} else if (cleanup_state_ == CLEANUP_RUNNING) {
@@ -904,15 +926,6 @@
return next_sequence_task_number_++;
}
-SequencedWorkerPool::WorkerShutdown
-SequencedWorkerPool::Inner::LockedCurrentThreadShutdownBehavior() const {
- lock_.AssertAcquired();
- ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
- if (found == threads_.end())
- return CONTINUE_ON_SHUTDOWN;
- return found->second->running_shutdown_behavior();
-}
-
SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
SequencedTask* task,
TimeDelta* wait_time,
diff --git a/base/threading/sequenced_worker_pool.h b/base/threading/sequenced_worker_pool.h
index 63c6204..0b6c5f9 100644
--- a/base/threading/sequenced_worker_pool.h
+++ b/base/threading/sequenced_worker_pool.h
@@ -320,12 +320,10 @@
// Must be called from the same thread this object was constructed on.
void Shutdown() { Shutdown(0); }
- // A variant that allows an arbitrary number of new blocking tasks to
- // be posted during shutdown from within tasks that execute during shutdown.
- // Only tasks designated as BLOCKING_SHUTDOWN will be allowed, and only if
- // posted by tasks that are not designated as CONTINUE_ON_SHUTDOWN. Once
+ // A variant that allows an arbitrary number of new blocking tasks to be
+ // posted during shutdown. The tasks cannot be posted within the execution
+ // context of tasks whose shutdown behavior is not BLOCKING_SHUTDOWN. Once
// the limit is reached, subsequent calls to post task fail in all cases.
- //
// Must be called from the same thread this object was constructed on.
void Shutdown(int max_new_blocking_tasks_after_shutdown);
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index 5d0880c..c12156e 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -159,6 +159,16 @@
FROM_HERE, reposting_task, SequencedWorkerPool::BLOCK_SHUTDOWN);
}
+ void PostBlockingTaskThenUnblockThreads(
+ const scoped_refptr<SequencedWorkerPool>& pool,
+ ThreadBlocker* blocker,
+ size_t threads_to_wake) {
+ Closure arbitrary_task = base::Bind(&TestTracker::FastTask, this, 0);
+ pool->PostWorkerTaskWithShutdownBehavior(
+ FROM_HERE, arbitrary_task, SequencedWorkerPool::BLOCK_SHUTDOWN);
+ blocker->Unblock(threads_to_wake);
+ }
+
// Waits until the given number of tasks have started executing.
void WaitUntilTasksBlocked(size_t count) {
{
@@ -287,7 +297,7 @@
// Checks that the given number of entries are in the tasks to complete of
// the given tracker, and then signals the given event the given number of
-// times. This is used to wakt up blocked background threads before blocking
+// times. This is used to wake up blocked background threads before blocking
// on shutdown.
void EnsureTasksToCompleteCountAndUnblock(scoped_refptr<TestTracker> tracker,
size_t expected_tasks_to_complete,
@@ -583,6 +593,34 @@
tracker()->ClearCompleteSequence();
}
+// Tests that blocking tasks can still be posted during shutdown, as long as
+// the task is not being posted within the context of a running task.
+TEST_F(SequencedWorkerPoolTest,
+ AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) {
+ EnsureAllWorkersCreated();
+ ThreadBlocker blocker;
+
+ // Start tasks to take all the threads and block them.
+ const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads);
+ for (int i = 0; i < kNumBlockTasks; ++i) {
+ EXPECT_TRUE(pool()->PostWorkerTask(
+ FROM_HERE,
+ base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker)));
+ }
+ tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
+
+ // Setup to open the floodgates from within Shutdown().
+ SetWillWaitForShutdownCallback(
+ base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads,
+ scoped_refptr<TestTracker>(tracker()), pool(), &blocker,
+ kNumWorkerThreads));
+ pool()->Shutdown(kNumWorkerThreads + 1);
+
+ // Ensure that the correct number of tasks actually got run.
+ tracker()->WaitUntilTasksComplete(static_cast<size_t>(kNumWorkerThreads + 1));
+ tracker()->ClearCompleteSequence();
+}
+
// Tests that unrun tasks are discarded properly according to their shutdown
// mode.
TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) {
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index ea5b174..d42ba4d 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -95,11 +95,6 @@
}
bool Thread::StartWithOptions(const Options& options) {
- // TODO(eroman): Remove once crbug.com/465458 is solved.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "465458 base::Thread::StartWithOptions"));
-
DCHECK(!message_loop_);
#if defined(OS_WIN)
DCHECK((com_status_ != STA) ||
@@ -117,7 +112,7 @@
return false;
}
- // TODO(eroman): Remove once crbug.com/465458 is solved.
+ // TODO(kinuko): Remove once crbug.com/465458 is solved.
tracked_objects::ScopedTracker tracking_profile_wait(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"465458 base::Thread::StartWithOptions (Wait)"));
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc
index b53f577..bcc1d1b 100644
--- a/base/threading/thread_local_storage_unittest.cc
+++ b/base/threading/thread_local_storage_unittest.cc
@@ -79,17 +79,16 @@
EXPECT_EQ(value, 123);
}
-#if defined(THREAD_SANITIZER) || \
- (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && \
- defined(INCREMENTAL_LINKING))
+#if defined(THREAD_SANITIZER) || \
+ (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && !defined(NDEBUG))
// Do not run the test under ThreadSanitizer. Because this test iterates its
// own TSD destructor for the maximum possible number of times, TSan can't jump
// in after the last destructor invocation, therefore the destructor remains
// unsynchronized with the following users of the same TSD slot. This results
// in race reports between the destructor and functions in other tests.
//
-// It is disabled on Win x64 with incremental linking pending resolution of
-// http://crbug.com/251251.
+// It is disabled on Win x64 with incremental linking (i.e. "Debug") pending
+// resolution of http://crbug.com/251251.
#define MAYBE_TLSDestructors DISABLED_TLSDestructors
#else
#define MAYBE_TLSDestructors TLSDestructors
diff --git a/base/threading/thread_local_unittest.cc b/base/threading/thread_local_unittest.cc
index 8dc7cd2..e94c1db 100644
--- a/base/threading/thread_local_unittest.cc
+++ b/base/threading/thread_local_unittest.cc
@@ -14,7 +14,7 @@
class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
public:
- typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType;
+ typedef base::ThreadLocalPointer<char> TLPType;
ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
: tlp_(tlp),
@@ -35,7 +35,7 @@
}
~SetThreadLocal() override {}
- void set_value(ThreadLocalTesterBase* val) { val_ = val; }
+ void set_value(char* val) { val_ = val; }
void Run() override {
DCHECK(!done_->IsSignaled());
@@ -44,7 +44,7 @@
}
private:
- ThreadLocalTesterBase* val_;
+ char* val_;
};
class GetThreadLocal : public ThreadLocalTesterBase {
@@ -55,7 +55,7 @@
}
~GetThreadLocal() override {}
- void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
+ void set_ptr(char** ptr) { ptr_ = ptr; }
void Run() override {
DCHECK(!done_->IsSignaled());
@@ -64,7 +64,7 @@
}
private:
- ThreadLocalTesterBase** ptr_;
+ char** ptr_;
};
} // namespace
@@ -77,12 +77,11 @@
tp1.Start();
tp2.Start();
- base::ThreadLocalPointer<ThreadLocalTesterBase> tlp;
+ base::ThreadLocalPointer<char> tlp;
- static ThreadLocalTesterBase* const kBogusPointer =
- reinterpret_cast<ThreadLocalTesterBase*>(0x1234);
+ static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
- ThreadLocalTesterBase* tls_val;
+ char* tls_val;
base::WaitableEvent done(true, false);
GetThreadLocal getter(&tlp, &done);
@@ -93,13 +92,13 @@
done.Reset();
tp1.AddWork(&getter);
done.Wait();
- EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+ EXPECT_EQ(static_cast<char*>(NULL), tls_val);
tls_val = kBogusPointer;
done.Reset();
tp2.AddWork(&getter);
done.Wait();
- EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+ EXPECT_EQ(static_cast<char*>(NULL), tls_val);
SetThreadLocal setter(&tlp, &done);
@@ -121,7 +120,7 @@
done.Reset();
tp2.AddWork(&getter);
done.Wait();
- EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+ EXPECT_EQ(static_cast<char*>(NULL), tls_val);
// Set thread 2 to kBogusPointer + 1.
setter.set_value(kBogusPointer + 1);
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
index b94f942..a08cc5b 100644
--- a/base/threading/thread_perftest.cc
+++ b/base/threading/thread_perftest.cc
@@ -174,12 +174,12 @@
template <typename WaitableEventType>
class EventPerfTest : public ThreadPerfTest {
public:
- virtual void Init() override {
+ void Init() override {
for (size_t i = 0; i < threads_.size(); i++)
events_.push_back(new WaitableEventType(false, false));
}
- virtual void Reset() override { events_.clear(); }
+ void Reset() override { events_.clear(); }
void WaitAndSignalOnThread(size_t event) {
size_t next_event = (event + 1) % events_.size();
@@ -195,7 +195,7 @@
FinishMeasurement();
}
- virtual void PingPong(int hops) override {
+ void PingPong(int hops) override {
remaining_hops_ = hops;
for (size_t i = 0; i < threads_.size(); i++) {
threads_[i]->message_loop_proxy()->PostTask(
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 75d8925..54f50eb 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -42,6 +42,7 @@
class NestedMessagePumpAndroid;
class RenderWidgetResizeHelper;
class ScopedAllowWaitForAndroidLayoutTests;
+class ScopedAllowWaitForDebugURL;
class TextInputClientMac;
} // namespace content
namespace dbus {
@@ -175,6 +176,7 @@
friend class content::NestedMessagePumpAndroid;
friend class content::RenderWidgetResizeHelper;
friend class content::ScopedAllowWaitForAndroidLayoutTests;
+ friend class content::ScopedAllowWaitForDebugURL;
friend class ::HistogramSynchronizer;
friend class ::ScopedAllowWaitForLegacyWebViewApi;
friend class cc::CompletionEvent;
diff --git a/base/time/time.cc b/base/time/time.cc
index 321323b..bf6c998 100644
--- a/base/time/time.cc
+++ b/base/time/time.cc
@@ -4,12 +4,12 @@
#include "base/time/time.h"
+#include <cmath>
#include <ios>
#include <limits>
#include <ostream>
#include <sstream>
-#include "base/float_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
@@ -161,7 +161,7 @@
// static
Time Time::FromDoubleT(double dt) {
- if (dt == 0 || IsNaN(dt))
+ if (dt == 0 || std::isnan(dt))
return Time(); // Preserve 0 so we can tell it doesn't exist.
if (dt == std::numeric_limits<double>::infinity())
return Max();
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn
index 479a918..4f3819d 100644
--- a/base/trace_event/BUILD.gn
+++ b/base/trace_event/BUILD.gn
@@ -4,13 +4,19 @@
source_set("trace_event") {
sources = [
- "memory_allocator_attributes.h",
+ "java_heap_dump_provider_android.cc",
+ "java_heap_dump_provider_android.h",
+ "memory_allocator_attributes_type_info.cc",
+ "memory_allocator_attributes_type_info.h",
"memory_allocator_dump.cc",
"memory_allocator_dump.h",
"memory_dump_manager.cc",
"memory_dump_manager.h",
"memory_dump_provider.cc",
"memory_dump_provider.h",
+ "memory_dump_request_args.h",
+ "memory_dump_session_state.cc",
+ "memory_dump_session_state.h",
"process_memory_dump.cc",
"process_memory_dump.h",
"process_memory_maps.cc",
@@ -25,6 +31,8 @@
"trace_event_android.cc",
"trace_event_argument.cc",
"trace_event_argument.h",
+ "trace_event_etw_export_win.cc",
+ "trace_event_etw_export_win.h",
"trace_event_impl.cc",
"trace_event_impl.h",
"trace_event_impl_constants.cc",
@@ -36,6 +44,8 @@
"trace_event_system_stats_monitor.h",
"trace_event_win.cc",
"trace_event_win.h",
+ "winheap_dump_provider_win.cc",
+ "winheap_dump_provider_win.h",
]
if (is_nacl) {
@@ -45,6 +55,13 @@
]
}
+ if (is_linux || is_android) {
+ sources += [
+ "malloc_dump_provider.cc",
+ "malloc_dump_provider.h",
+ ]
+ }
+
configs += [ "//base:base_implementation" ]
deps = [
@@ -55,6 +72,10 @@
"//base/third_party/dynamic_annotations",
]
+ if (is_win) {
+ deps += [ "//base/trace_event/etw_manifest:chrome_events_win" ]
+ }
+
allow_circular_includes_from = [
"//base/debug",
"//base/memory",
@@ -67,6 +88,7 @@
source_set("trace_event_unittests") {
testonly = true
sources = [
+ "memory_allocator_attributes_type_info_unittest.cc",
"memory_allocator_dump_unittest.cc",
"memory_dump_manager_unittest.cc",
"process_memory_maps_dump_provider_unittest.cc",
@@ -77,6 +99,7 @@
"trace_event_system_stats_monitor_unittest.cc",
"trace_event_unittest.cc",
"trace_event_win_unittest.cc",
+ "winheap_dump_provider_win_unittest.cc",
]
deps = [
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS
index 3932776..aa1d675 100644
--- a/base/trace_event/OWNERS
+++ b/base/trace_event/OWNERS
@@ -1,3 +1,4 @@
nduca@chromium.org
dsinclair@chromium.org
+primiano@chromium.org
per-file trace_event_android.cc=wangxianzhu@chromium.org
diff --git a/base/trace_event/etw_manifest/BUILD.gn b/base/trace_event/etw_manifest/BUILD.gn
new file mode 100644
index 0000000..07cf80e
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD.gn
@@ -0,0 +1,37 @@
+# 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.
+
+assert(is_win, "This only runs on Windows.")
+
+# Makes the .h/.rc files from the .man file.
+action("chrome_events_win") {
+ visibility = [
+ "//base/trace_event/*",
+ "//chrome:main_dll",
+ ]
+ script = "build/message_compiler.py"
+
+ sources = [
+ "chrome_events_win.man",
+ ]
+
+ outputs = [
+ "$target_gen_dir/chrome_events_win.h",
+ "$target_gen_dir/chrome_events_win.rc",
+ ]
+
+ args = [
+ # Where to put the header.
+ "-h",
+ rebase_path("$target_gen_dir", root_build_dir),
+
+ # Where to put the .rc file.
+ "-r",
+ rebase_path("$target_gen_dir", root_build_dir),
+
+ # Generate the user-mode code.
+ "-um",
+ rebase_path("chrome_events_win.man", root_build_dir),
+ ]
+}
diff --git a/base/trace_event/etw_manifest/BUILD/message_compiler.py b/base/trace_event/etw_manifest/BUILD/message_compiler.py
new file mode 100644
index 0000000..be5927d
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD/message_compiler.py
@@ -0,0 +1,16 @@
+# 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.
+
+# Runs the Microsoft Message Compiler (mc.exe). This Python adapter is for the
+# GN build, which can only run Python and not native binaries.
+
+import subprocess
+import sys
+
+# mc writes to stderr, so this explicily redirects to stdout and eats it.
+try:
+ subprocess.check_output(["mc.exe"] + sys.argv[1:], stderr=subprocess.STDOUT)
+except subprocess.CalledProcessError as e:
+ print e.output
+ sys.exit(e.returncode)
diff --git a/base/trace_event/etw_manifest/chrome_events_win.man b/base/trace_event/etw_manifest/chrome_events_win.man
new file mode 100644
index 0000000..10a8ddf
--- /dev/null
+++ b/base/trace_event/etw_manifest/chrome_events_win.man
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes'?>
+<instrumentationManifest
+ xmlns="http://schemas.microsoft.com/win/2004/08/events"
+ xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
+ >
+ <instrumentation>
+ <events>
+ <provider
+ guid="{D2D578D9-2936-45B6-A09f-30E32715F42D}"
+ messageFileName="chrome.dll"
+ name="Chrome"
+ resourceFileName="chrome.dll"
+ symbol="CHROME"
+ >
+ <channels>
+ <importChannel
+ chid="SYSTEM"
+ name="System"
+ />
+ </channels>
+ <templates>
+ <template tid="tid_chrome_event">
+ <data
+ inType="win:AnsiString"
+ name="Name"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Phase"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 1"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 1"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 2"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 2"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Name 3"
+ />
+ <data
+ inType="win:AnsiString"
+ name="Arg Value 3"
+ />
+ </template>
+ </templates>
+ <events>
+ <event
+ channel="SYSTEM"
+ level="win:Informational"
+ message="$(string.ChromeEvent.EventMessage)"
+ opcode="win:Info"
+ symbol="ChromeEvent"
+ template="tid_chrome_event"
+ value="1"
+ />
+ </events>
+ </provider>
+ </events>
+ </instrumentation>
+ <localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
+ <resources culture="en-US">
+ <stringTable>
+ <string
+ id="ChromeEvent.EventMessage"
+ value="Chrome Event: %1 (%2)"
+ />
+ </stringTable>
+ </resources>
+ </localization>
+</instrumentationManifest>
diff --git a/base/trace_event/etw_manifest/etw_manifest.gyp b/base/trace_event/etw_manifest/etw_manifest.gyp
new file mode 100644
index 0000000..b0a8712
--- /dev/null
+++ b/base/trace_event/etw_manifest/etw_manifest.gyp
@@ -0,0 +1,39 @@
+# 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.
+{
+ 'targets': [
+ {
+ # GN version: //base/trace_event/etw_manifest/BUILD.gn
+ 'target_name': 'etw_manifest',
+ 'type': 'static_library',
+ 'conditions': [
+ ['OS=="win"', {
+ 'sources': [
+ 'chrome_events_win.man',
+ ],
+ 'variables': {
+ 'man_output_dir': '<(SHARED_INTERMEDIATE_DIR)/base/trace_event/etw_manifest',
+ },
+ 'rules': [{
+ # Rule to run the message compiler.
+ 'rule_name': 'message_compiler',
+ 'extension': 'man',
+ 'outputs': [
+ '<(man_output_dir)/chrome_events_win.h',
+ '<(man_output_dir)/chrome_events_win.rc',
+ ],
+ 'action': [
+ 'mc.exe',
+ '-h', '<(man_output_dir)',
+ '-r', '<(man_output_dir)/.',
+ '-um',
+ '<(RULE_INPUT_PATH)',
+ ],
+ 'message': 'Running message compiler on <(RULE_INPUT_PATH)',
+ }],
+ }],
+ ],
+ }
+ ]
+}
diff --git a/base/trace_event/java_heap_dump_provider_android.cc b/base/trace_event/java_heap_dump_provider_android.cc
new file mode 100644
index 0000000..aa193ab
--- /dev/null
+++ b/base/trace_event/java_heap_dump_provider_android.cc
@@ -0,0 +1,53 @@
+// 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/trace_event/java_heap_dump_provider_android.h"
+
+#include "base/android/java_runtime.h"
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "JavaHeap";
+const char kDumperName[] = "java_heap";
+
+} // namespace
+
+// static
+JavaHeapDumpProvider* JavaHeapDumpProvider::GetInstance() {
+ return Singleton<JavaHeapDumpProvider,
+ LeakySingletonTraits<JavaHeapDumpProvider>>::get();
+}
+
+JavaHeapDumpProvider::JavaHeapDumpProvider() {
+}
+
+JavaHeapDumpProvider::~JavaHeapDumpProvider() {
+}
+
+// Called at trace dump point time. Creates a snapshot with the memory counters
+// for the current process.
+bool JavaHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+ MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(kDumperName, MemoryAllocatorDump::kRootHeap);
+
+ // These numbers come from java.lang.Runtime stats.
+ long total_heap_size = 0;
+ long free_heap_size = 0;
+ android::JavaRuntime::GetMemoryUsage(&total_heap_size, &free_heap_size);
+ dump->set_physical_size_in_bytes(total_heap_size);
+ dump->set_allocated_objects_count(0);
+ dump->set_allocated_objects_size_in_bytes(total_heap_size - free_heap_size);
+ return true;
+}
+
+const char* JavaHeapDumpProvider::GetFriendlyName() const {
+ return kDumperFriendlyName;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/java_heap_dump_provider_android.h b/base/trace_event/java_heap_dump_provider_android.h
new file mode 100644
index 0000000..8280751
--- /dev/null
+++ b/base/trace_event/java_heap_dump_provider_android.h
@@ -0,0 +1,35 @@
+// 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 BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
+#define BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// Dump provider which collects process-wide memory stats.
+class JavaHeapDumpProvider : public MemoryDumpProvider {
+ public:
+ static JavaHeapDumpProvider* GetInstance();
+
+ // MemoryDumpProvider implementation.
+ bool DumpInto(ProcessMemoryDump* pmd) override;
+ const char* GetFriendlyName() const override;
+
+ private:
+ friend struct DefaultSingletonTraits<JavaHeapDumpProvider>;
+
+ JavaHeapDumpProvider();
+ ~JavaHeapDumpProvider() override;
+
+ DISALLOW_COPY_AND_ASSIGN(JavaHeapDumpProvider);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc
new file mode 100644
index 0000000..7d9931c
--- /dev/null
+++ b/base/trace_event/malloc_dump_provider.cc
@@ -0,0 +1,64 @@
+// 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/trace_event/malloc_dump_provider.h"
+
+#include <malloc.h>
+
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "Malloc";
+
+} // namespace
+
+// static
+MallocDumpProvider* MallocDumpProvider::GetInstance() {
+ return Singleton<MallocDumpProvider,
+ LeakySingletonTraits<MallocDumpProvider>>::get();
+}
+
+MallocDumpProvider::MallocDumpProvider() {
+}
+
+MallocDumpProvider::~MallocDumpProvider() {
+}
+
+// Called at trace dump point time. Creates a snapshot the memory counters for
+// the current process.
+bool MallocDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+ struct mallinfo info = mallinfo();
+ DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
+
+ MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump("malloc", MemoryAllocatorDump::kRootHeap);
+ if (!dump)
+ return false;
+
+ // When the system allocator is implemented by tcmalloc, the total physical
+ // size is given by |arena| and |hblkhd| is 0. In case of Android's jemalloc
+ // |arena| is 0 and the outer pages size is reported by |hblkhd|. In case of
+ // dlmalloc the total is given by |arena| + |hblkhd|.
+ // For more details see link: http://goo.gl/fMR8lF.
+ dump->set_physical_size_in_bytes(info.arena + info.hblkhd);
+
+ // mallinfo doesn't support any allocated object count.
+ dump->set_allocated_objects_count(0);
+
+ // Total allocated space is given by |uordblks|.
+ dump->set_allocated_objects_size_in_bytes(info.uordblks);
+
+ return true;
+}
+
+const char* MallocDumpProvider::GetFriendlyName() const {
+ return kDumperFriendlyName;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h
new file mode 100644
index 0000000..b6f6973
--- /dev/null
+++ b/base/trace_event/malloc_dump_provider.h
@@ -0,0 +1,37 @@
+// 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 BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
+#define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
+
+#include <istream>
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// Dump provider which collects process-wide memory stats.
+class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider {
+ public:
+ static MallocDumpProvider* GetInstance();
+
+ // MemoryDumpProvider implementation.
+ bool DumpInto(ProcessMemoryDump* pmd) override;
+ const char* GetFriendlyName() const override;
+
+ private:
+ friend struct DefaultSingletonTraits<MallocDumpProvider>;
+
+ MallocDumpProvider();
+ ~MallocDumpProvider() override;
+
+ DISALLOW_COPY_AND_ASSIGN(MallocDumpProvider);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_allocator_attributes.h b/base/trace_event/memory_allocator_attributes.h
deleted file mode 100644
index efae9de..0000000
--- a/base/trace_event/memory_allocator_attributes.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
-#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/containers/hash_tables.h"
-
-namespace base {
-namespace trace_event {
-
-struct BASE_EXPORT MemoryAllocatorDeclaredAttribute {
- std::string name;
-
- // Refer to src/tools/perf/unit-info.json for the semantic of the type.
- std::string type;
-};
-
-using MemoryAllocatorDeclaredAttributes =
- hash_map<std::string, MemoryAllocatorDeclaredAttribute>;
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
diff --git a/base/trace_event/memory_allocator_attributes_type_info.cc b/base/trace_event/memory_allocator_attributes_type_info.cc
new file mode 100644
index 0000000..7d1e61c
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info.cc
@@ -0,0 +1,61 @@
+// 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/trace_event/memory_allocator_attributes_type_info.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+base::LazyInstance<const std::string> kNotFound = LAZY_INSTANCE_INITIALIZER;
+
+std::string GetKey(const std::string& allocator_name,
+ const std::string& attribute_name) {
+ return allocator_name + "/" + attribute_name;
+}
+} // namespace
+
+MemoryAllocatorAttributesTypeInfo::MemoryAllocatorAttributesTypeInfo() {
+}
+
+MemoryAllocatorAttributesTypeInfo::~MemoryAllocatorAttributesTypeInfo() {
+}
+
+const std::string& MemoryAllocatorAttributesTypeInfo::Get(
+ const std::string& allocator_name,
+ const std::string& attribute_name) const {
+ auto it = type_info_map_.find(GetKey(allocator_name, attribute_name));
+ if (it == type_info_map_.end())
+ return kNotFound.Get();
+ return it->second;
+}
+
+void MemoryAllocatorAttributesTypeInfo::Set(const std::string& allocator_name,
+ const std::string& attribute_name,
+ const std::string& attribute_type) {
+ std::string key = GetKey(allocator_name, attribute_name);
+ DCHECK_EQ(0u, type_info_map_.count(key));
+ type_info_map_[key] = attribute_type;
+}
+
+bool MemoryAllocatorAttributesTypeInfo::Exists(
+ const std::string& allocator_name,
+ const std::string& attribute_name) const {
+ return type_info_map_.count(GetKey(allocator_name, attribute_name)) == 1;
+}
+
+void MemoryAllocatorAttributesTypeInfo::Update(
+ const MemoryAllocatorAttributesTypeInfo& other) {
+ for (auto it = other.type_info_map_.begin();
+ it != other.type_info_map_.end(); ++it) {
+ bool no_duplicates = type_info_map_.insert(*it).second;
+ DCHECK(no_duplicates) << "Duplicated allocator attribute " << it->first;
+ }
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/memory_allocator_attributes_type_info.h b/base/trace_event/memory_allocator_attributes_type_info.h
new file mode 100644
index 0000000..c3986ae
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info.h
@@ -0,0 +1,49 @@
+// 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 BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
+#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/containers/hash_tables.h"
+
+namespace base {
+namespace trace_event {
+
+// A dictionary of "allocator_name/attribute_name" -> "attribute_type" which
+// supports merging and enforces duplicate checking.
+class BASE_EXPORT MemoryAllocatorAttributesTypeInfo {
+ public:
+ MemoryAllocatorAttributesTypeInfo();
+ ~MemoryAllocatorAttributesTypeInfo();
+
+ // Returns the attribute type, or an empty string if not found.
+ const std::string& Get(const std::string& allocator_name,
+ const std::string& attribute_name) const;
+
+ // Refer to tools/perf/unit-info.json for the semantics of |attribute_type|.
+ void Set(const std::string& allocator_name,
+ const std::string& attribute_name,
+ const std::string& attribute_type);
+
+ // Checks whether a given {allocator_name, attribute_name} declaration exists.
+ bool Exists(const std::string& allocator_name,
+ const std::string& attribute_name) const;
+
+ // Merges the attribute types declared in |other| into this.
+ void Update(const MemoryAllocatorAttributesTypeInfo& other);
+
+ private:
+ // "allocator_name/attribute_name" -> attribute_type.
+ hash_map<std::string, std::string> type_info_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorAttributesTypeInfo);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
diff --git a/base/trace_event/memory_allocator_attributes_type_info_unittest.cc b/base/trace_event/memory_allocator_attributes_type_info_unittest.cc
new file mode 100644
index 0000000..5f69fae
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace trace_event {
+
+TEST(MemoryAllocatorAttributesTypeInfoTest, BasicTest) {
+ MemoryAllocatorAttributesTypeInfo attrs;
+ EXPECT_EQ("", attrs.Get("non_existing_alloc", "non_existing_attr"));
+
+ attrs.Set("alloc", "attr", "type");
+ EXPECT_TRUE(attrs.Exists("alloc", "attr"));
+ EXPECT_FALSE(attrs.Exists("alloc", "foo"));
+ EXPECT_FALSE(attrs.Exists("foo", "attr"));
+ EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+
+ attrs.Set("alloc2", "attr", "type2");
+ EXPECT_TRUE(attrs.Exists("alloc2", "attr"));
+ EXPECT_FALSE(attrs.Exists("alloc2", "foo"));
+ EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+ EXPECT_EQ("type2", attrs.Get("alloc2", "attr"));
+
+ MemoryAllocatorAttributesTypeInfo other_attrs;
+ other_attrs.Set("other_alloc", "other_attr", "other_type");
+ other_attrs.Set("other_alloc", "attr", "other_type2");
+ other_attrs.Set("other_alloc_2", "other_attr", "other_type");
+ other_attrs.Set("other_alloc_2", "attr", "other_type3");
+
+ // Check the merging logic.
+ attrs.Update(other_attrs);
+ EXPECT_EQ("other_type", attrs.Get("other_alloc", "other_attr"));
+ EXPECT_EQ("other_type2", attrs.Get("other_alloc", "attr"));
+ EXPECT_EQ("other_type", attrs.Get("other_alloc_2", "other_attr"));
+ EXPECT_EQ("other_type3", attrs.Get("other_alloc_2", "attr"));
+ EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+ EXPECT_EQ("type2", attrs.Get("alloc2", "attr"));
+ EXPECT_FALSE(other_attrs.Exists("alloc", "attr"));
+ EXPECT_FALSE(other_attrs.Exists("alloc2", "attr"));
+}
+
+// DEATH tests are not supported in Android / iOS.
+#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
+TEST(MemoryAllocatorAttributesTypeInfoTest, DuplicatesDeathTest) {
+ MemoryAllocatorAttributesTypeInfo attrs;
+ attrs.Set("alloc", "attr", "type");
+ MemoryAllocatorAttributesTypeInfo conflicting_attrs;
+ conflicting_attrs.Set("alloc", "attr", "type2");
+ ASSERT_DEATH(attrs.Set("alloc", "attr", "other_type"), "");
+ ASSERT_DEATH(attrs.Update(conflicting_attrs), "");
+}
+#endif
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc
index 604af7a..1d2fb3f 100644
--- a/base/trace_event/memory_allocator_dump.cc
+++ b/base/trace_event/memory_allocator_dump.cc
@@ -6,85 +6,122 @@
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_allocator_attributes.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
#include "base/values.h"
namespace base {
namespace trace_event {
-MemoryAllocatorDump::MemoryAllocatorDump(const std::string& name,
- MemoryAllocatorDump* parent)
- : name_(name),
- parent_(parent),
+// static
+const char MemoryAllocatorDump::kRootHeap[] = "";
+
+// static
+std::string MemoryAllocatorDump::GetAbsoluteName(
+ const std::string& allocator_name,
+ const std::string& heap_name) {
+ return allocator_name + (heap_name == kRootHeap ? "" : "/" + heap_name);
+}
+
+MemoryAllocatorDump::MemoryAllocatorDump(const std::string& allocator_name,
+ const std::string& heap_name,
+ ProcessMemoryDump* process_memory_dump)
+ : allocator_name_(allocator_name),
+ heap_name_(heap_name),
+ process_memory_dump_(process_memory_dump),
physical_size_in_bytes_(0),
allocated_objects_count_(0),
allocated_objects_size_in_bytes_(0) {
- // Dots are not allowed in the name as the underlying base::DictionaryValue
+ // The allocator name cannot be empty or contain slash separators.
+ DCHECK(!allocator_name.empty());
+ DCHECK_EQ(std::string::npos, allocator_name.find_first_of('/'));
+
+ // The heap_name can be empty and contain slash separator, but not
+ // leading or trailing ones.
+ DCHECK(heap_name.empty() ||
+ (heap_name[0] != '/' && *heap_name.rbegin() != '/'));
+
+ // Dots are not allowed anywhere as the underlying base::DictionaryValue
// would treat them magically and split in sub-nodes, which is not intended.
- DCHECK_EQ(std::string::npos, name.find_first_of('.'));
+ DCHECK_EQ(std::string::npos, allocator_name.find_first_of('.'));
+ DCHECK_EQ(std::string::npos, heap_name.find_first_of('.'));
}
MemoryAllocatorDump::~MemoryAllocatorDump() {
}
-void MemoryAllocatorDump::SetExtraAttribute(const std::string& name,
- int value) {
- extra_attributes_.SetInteger(name, value);
+void MemoryAllocatorDump::SetAttribute(const std::string& name, int value) {
+ DCHECK(GetAttributesTypeInfo().Exists(allocator_name_, name))
+ << "attribute '" << name << "' not declared."
+ << "See MemoryDumpProvider.DeclareAllocatorAttribute()";
+ attributes_values_.SetInteger(name, value);
}
-int MemoryAllocatorDump::GetExtraIntegerAttribute(
- const std::string& name) const {
- bool res;
+std::string MemoryAllocatorDump::GetAbsoluteName() const {
+ return GetAbsoluteName(allocator_name_, heap_name_);
+}
+
+int MemoryAllocatorDump::GetIntegerAttribute(const std::string& name) const {
int value = -1;
- res = extra_attributes_.GetInteger(name, &value);
- DCHECK(res) << "Allocator attribute '" << name << "' not found";
+ bool res = attributes_values_.GetInteger(name, &value);
+ DCHECK(res) << "Attribute '" << name << "' not found";
return value;
}
void MemoryAllocatorDump::AsValueInto(TracedValue* value) const {
static const char kHexFmt[] = "%" PRIx64;
- value->BeginDictionary(name_.c_str());
+ value->BeginDictionary(GetAbsoluteName().c_str());
+ value->BeginDictionary("attrs");
- value->SetString("parent", parent_ ? parent_->name_ : "");
- value->SetString("physical_size_in_bytes",
- StringPrintf(kHexFmt, physical_size_in_bytes_));
- value->SetString("allocated_objects_count",
- StringPrintf(kHexFmt, allocated_objects_count_));
- value->SetString("allocated_objects_size_in_bytes",
+ // TODO(primiano): these hard-coded types are temporary to transition to the
+ // new generalized attribute format. This code will be refactored by the end
+ // of May 2015.
+ value->BeginDictionary("outer_size");
+ value->SetString("type", "scalar");
+ value->SetString("units", "bytes");
+ value->SetString("value", StringPrintf(kHexFmt, physical_size_in_bytes_));
+ value->EndDictionary();
+
+ value->BeginDictionary("inner_size");
+ value->SetString("type", "scalar");
+ value->SetString("units", "bytes");
+ value->SetString("value",
StringPrintf(kHexFmt, allocated_objects_size_in_bytes_));
+ value->EndDictionary();
+
+ value->BeginDictionary("objects_count");
+ value->SetString("type", "scalar");
+ value->SetString("units", "objects");
+ value->SetString("value", StringPrintf(kHexFmt, allocated_objects_count_));
+ value->EndDictionary();
// Copy all the extra attributes.
- const MemoryDumpProvider* mdp =
- MemoryDumpManager::GetInstance()->dump_provider_currently_active();
- const MemoryAllocatorDeclaredAttributes& extra_attributes_types =
- mdp->allocator_attributes();
-
- value->BeginDictionary("args");
- for (DictionaryValue::Iterator it(extra_attributes_); !it.IsAtEnd();
+ for (DictionaryValue::Iterator it(attributes_values_); !it.IsAtEnd();
it.Advance()) {
const std::string& attr_name = it.key();
const Value& attr_value = it.value();
value->BeginDictionary(attr_name.c_str());
value->SetValue("value", attr_value.DeepCopy());
- auto attr_it = extra_attributes_types.find(attr_name);
- DCHECK(attr_it != extra_attributes_types.end())
- << "Allocator attribute " << attr_name
- << " not declared for the dumper " << mdp->GetFriendlyName();
-
- // TODO(primiano): the "type" should be dumped just once, not repeated on
- // on every event. The ability of doing so depends on crbug.com/466121.
- value->SetString("type", attr_it->second.type);
+ const std::string& attr_type =
+ GetAttributesTypeInfo().Get(allocator_name_, attr_name);
+ DCHECK(!attr_type.empty());
+ value->SetString("type", "scalar");
+ value->SetString("units", attr_type);
value->EndDictionary(); // "arg_name": { "type": "...", "value": "..." }
}
- value->EndDictionary(); // "args": {}
- value->EndDictionary(); // "allocator name": {}
+ value->EndDictionary(); // "attrs": { ... }
+ value->EndDictionary(); // "allocator_name/heap_subheap": { ... }
+}
+
+const MemoryAllocatorAttributesTypeInfo&
+MemoryAllocatorDump::GetAttributesTypeInfo() const {
+ return process_memory_dump_->session_state()->allocators_attributes_type_info;
}
} // namespace trace_event
diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h
index 4d7293e..1c786ab 100644
--- a/base/trace_event/memory_allocator_dump.h
+++ b/base/trace_event/memory_allocator_dump.h
@@ -8,34 +8,45 @@
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/logging.h"
-#include "base/trace_event/memory_allocator_attributes.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
#include "base/values.h"
namespace base {
namespace trace_event {
class MemoryDumpManager;
+class ProcessMemoryDump;
class TracedValue;
// Data model for user-land memory allocator dumps.
class BASE_EXPORT MemoryAllocatorDump {
public:
- MemoryAllocatorDump(const std::string& name, MemoryAllocatorDump* parent);
+ // Returns the absolute name for a given (|allocator_name|,|heap_name|) tuple.
+ static std::string GetAbsoluteName(const std::string& allocator_name,
+ const std::string& heap_name);
+
+ // Use as argument for |heap_name| when the allocator has only one root heap.
+ static const char kRootHeap[];
+
+ // MemoryAllocatorDump is owned by ProcessMemoryDump.
+ MemoryAllocatorDump(const std::string& allocator_name,
+ const std::string& heap_name,
+ ProcessMemoryDump* process_memory_dump);
~MemoryAllocatorDump();
- const std::string& name() const { return name_; }
- const MemoryAllocatorDump* parent() const { return parent_; }
+ // Name of the allocator, a plain string with no separators (e.g, "malloc").
+ const std::string& allocator_name() const { return allocator_name_; }
- void set_physical_size_in_bytes(uint64 value) {
- physical_size_in_bytes_ = value;
- }
- uint64 physical_size_in_bytes() const { return physical_size_in_bytes_; }
+ // Name of the heap being dumped, either: "heap", "heap/subheap" or kRootHeap
+ // if the allocator has just one root heap.
+ const std::string& heap_name() const { return heap_name_; }
- void set_allocated_objects_count(uint64 value) {
- allocated_objects_count_ = value;
- }
- uint64 allocated_objects_count() const { return allocated_objects_count_; }
+ // Absolute name, unique within the scope of an entire ProcessMemoryDump.
+ // In practice this is "allocator_name/heap/subheap".
+ std::string GetAbsoluteName() const;
+ // Inner size: Bytes requested by clients of the allocator, without accounting
+ // for any metadata or allocator-specific bookeeping structs.
void set_allocated_objects_size_in_bytes(uint64 value) {
allocated_objects_size_in_bytes_ = value;
}
@@ -43,19 +54,46 @@
return allocated_objects_size_in_bytes_;
}
- void SetExtraAttribute(const std::string& name, int value);
- int GetExtraIntegerAttribute(const std::string& name) const;
+ // Outer size: bytes requested to the system to handle all the allocations,
+ // including any allocator-internal metadata / bookeeping structs. For
+ // instance, in the case of an allocator which gets pages to the system via
+ // mmap() or similar, this is the number of requested pages * 4k.
+ void set_physical_size_in_bytes(uint64 value) {
+ physical_size_in_bytes_ = value;
+ }
+ uint64 physical_size_in_bytes() const { return physical_size_in_bytes_; }
+
+ // Number of objects allocated, if known, or 0 if not available.
+ void set_allocated_objects_count(uint64 value) {
+ allocated_objects_count_ = value;
+ }
+ uint64 allocated_objects_count() const { return allocated_objects_count_; }
+
+ // Get/Set extra attributes. The attributes name must have been previously
+ // declared through MemoryDumpProvider.DeclareAllocatorAttribute().
+ void SetAttribute(const std::string& name, int value);
+ int GetIntegerAttribute(const std::string& name) const;
// Called at trace generation time to populate the TracedValue.
void AsValueInto(TracedValue* value) const;
+ // Get the ProcessMemoryDump instance that owns this.
+ ProcessMemoryDump* process_memory_dump() const {
+ return process_memory_dump_;
+ }
+
+ // Retrieves the map of allocator attributes types, which is shared by all
+ // MemoryAllocatorDump(s) across all ProcessMemoryDump(s) per tracing session.
+ const MemoryAllocatorAttributesTypeInfo& GetAttributesTypeInfo() const;
+
private:
- const std::string name_;
- MemoryAllocatorDump* const parent_; // Not owned.
+ const std::string allocator_name_;
+ const std::string heap_name_;
+ ProcessMemoryDump* const process_memory_dump_; // Not owned (PMD owns this).
uint64 physical_size_in_bytes_;
uint64 allocated_objects_count_;
uint64 allocated_objects_size_in_bytes_;
- DictionaryValue extra_attributes_;
+ DictionaryValue attributes_values_;
DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump);
};
diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc
index 8c14560..110a25d 100644
--- a/base/trace_event/memory_allocator_dump_unittest.cc
+++ b/base/trace_event/memory_allocator_dump_unittest.cc
@@ -5,89 +5,110 @@
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace trace_event {
namespace {
+
class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider {
public:
FakeMemoryAllocatorDumpProvider() {
- DeclareAllocatorAttribute({"attr1", "count"});
- DeclareAllocatorAttribute({"attr2", "bytes"});
+ DeclareAllocatorAttribute("foobar_allocator", "attr1", "count");
+ DeclareAllocatorAttribute("foobar_allocator", "attr2", "bytes");
}
bool DumpInto(ProcessMemoryDump* pmd) override {
- MemoryAllocatorDump* mad_foo = pmd->CreateAllocatorDump("foo");
- mad_foo->set_physical_size_in_bytes(4096);
- mad_foo->set_allocated_objects_count(42);
- mad_foo->set_allocated_objects_size_in_bytes(1000);
- mad_foo->SetExtraAttribute("attr1", 1234);
- mad_foo->SetExtraAttribute("attr2", 99);
+ MemoryAllocatorDump* root_heap = pmd->CreateAllocatorDump(
+ "foobar_allocator", MemoryAllocatorDump::kRootHeap);
+ root_heap->set_physical_size_in_bytes(4096);
+ root_heap->set_allocated_objects_count(42);
+ root_heap->set_allocated_objects_size_in_bytes(1000);
+ root_heap->SetAttribute("attr1", 1234);
+ root_heap->SetAttribute("attr2", 99);
- MemoryAllocatorDump* mad_bar = pmd->CreateAllocatorDump("foo/bar", mad_foo);
- mad_bar->set_physical_size_in_bytes(1);
- mad_bar->set_allocated_objects_count(2);
- mad_bar->set_allocated_objects_size_in_bytes(3);
+ MemoryAllocatorDump* sub_heap =
+ pmd->CreateAllocatorDump("foobar_allocator", "sub_heap");
+ sub_heap->set_physical_size_in_bytes(1);
+ sub_heap->set_allocated_objects_count(2);
+ sub_heap->set_allocated_objects_size_in_bytes(3);
- pmd->CreateAllocatorDump("baz");
- // Leave the rest of |baz| deliberately uninitialized, to check that
+ pmd->CreateAllocatorDump("foobar_allocator", "sub_heap/empty");
+ // Leave the rest of sub heap deliberately uninitialized, to check that
// CreateAllocatorDump returns a properly zero-initialized object.
return true;
}
- const char* GetFriendlyName() const override { return "mock_allocator"; }
+ const char* GetFriendlyName() const override { return "FooBar Allocator"; }
};
} // namespace
TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
FakeMemoryAllocatorDumpProvider fmadp;
- ProcessMemoryDump pmd;
+ ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+ pmd.session_state()->allocators_attributes_type_info.Update(
+ fmadp.allocator_attributes_type_info());
fmadp.DumpInto(&pmd);
ASSERT_EQ(3u, pmd.allocator_dumps().size());
- const MemoryAllocatorDump* mad_foo = pmd.GetAllocatorDump("foo");
- ASSERT_NE(nullptr, mad_foo);
- EXPECT_EQ("foo", mad_foo->name());
- ASSERT_EQ(nullptr, mad_foo->parent());
- EXPECT_EQ(4096u, mad_foo->physical_size_in_bytes());
- EXPECT_EQ(42u, mad_foo->allocated_objects_count());
- EXPECT_EQ(1000u, mad_foo->allocated_objects_size_in_bytes());
+ const MemoryAllocatorDump* root_heap =
+ pmd.GetAllocatorDump("foobar_allocator", MemoryAllocatorDump::kRootHeap);
+ ASSERT_NE(nullptr, root_heap);
+ EXPECT_EQ("foobar_allocator", root_heap->allocator_name());
+ EXPECT_EQ("", root_heap->heap_name());
+ EXPECT_NE("", root_heap->GetAbsoluteName());
+ EXPECT_EQ(4096u, root_heap->physical_size_in_bytes());
+ EXPECT_EQ(42u, root_heap->allocated_objects_count());
+ EXPECT_EQ(1000u, root_heap->allocated_objects_size_in_bytes());
- // Check the extra attributes of |mad_foo|.
- EXPECT_EQ(1234, mad_foo->GetExtraIntegerAttribute("attr1"));
- EXPECT_EQ(99, mad_foo->GetExtraIntegerAttribute("attr2"));
+ // Check the extra attributes of |root_heap|.
+ EXPECT_EQ(1234, root_heap->GetIntegerAttribute("attr1"));
+ EXPECT_EQ(99, root_heap->GetIntegerAttribute("attr2"));
- const MemoryAllocatorDump* mad_bar = pmd.GetAllocatorDump("foo/bar");
- ASSERT_NE(nullptr, mad_bar);
- EXPECT_EQ("foo/bar", mad_bar->name());
- ASSERT_EQ(mad_foo, mad_bar->parent());
- EXPECT_EQ(1u, mad_bar->physical_size_in_bytes());
- EXPECT_EQ(2u, mad_bar->allocated_objects_count());
- EXPECT_EQ(3u, mad_bar->allocated_objects_size_in_bytes());
+ const MemoryAllocatorDump* sub_heap =
+ pmd.GetAllocatorDump("foobar_allocator", "sub_heap");
+ ASSERT_NE(nullptr, sub_heap);
+ EXPECT_EQ("foobar_allocator", sub_heap->allocator_name());
+ EXPECT_EQ("sub_heap", sub_heap->heap_name());
+ EXPECT_NE("", sub_heap->GetAbsoluteName());
+ EXPECT_EQ(1u, sub_heap->physical_size_in_bytes());
+ EXPECT_EQ(2u, sub_heap->allocated_objects_count());
+ EXPECT_EQ(3u, sub_heap->allocated_objects_size_in_bytes());
- const MemoryAllocatorDump* mad_baz = pmd.GetAllocatorDump("baz");
- ASSERT_NE(nullptr, mad_baz);
- EXPECT_EQ("baz", mad_baz->name());
- ASSERT_EQ(nullptr, mad_baz->parent());
- EXPECT_EQ(0u, mad_baz->physical_size_in_bytes());
- EXPECT_EQ(0u, mad_baz->allocated_objects_count());
- EXPECT_EQ(0u, mad_baz->allocated_objects_size_in_bytes());
+ const MemoryAllocatorDump* empty_sub_heap =
+ pmd.GetAllocatorDump("foobar_allocator", "sub_heap/empty");
+ ASSERT_NE(nullptr, empty_sub_heap);
+ EXPECT_EQ("foobar_allocator", empty_sub_heap->allocator_name());
+ EXPECT_EQ("sub_heap/empty", empty_sub_heap->heap_name());
+ EXPECT_NE("", sub_heap->GetAbsoluteName());
+ EXPECT_EQ(0u, empty_sub_heap->physical_size_in_bytes());
+ EXPECT_EQ(0u, empty_sub_heap->allocated_objects_count());
+ EXPECT_EQ(0u, empty_sub_heap->allocated_objects_size_in_bytes());
+
+ // Check that the AsValueInfo doesn't hit any DCHECK.
+ scoped_refptr<TracedValue> traced_value(new TracedValue());
+ pmd.AsValueInto(traced_value.get());
}
// DEATH tests are not supported in Android / iOS.
#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
FakeMemoryAllocatorDumpProvider fmadp;
- ProcessMemoryDump pmd;
- pmd.CreateAllocatorDump("dump_1");
- pmd.CreateAllocatorDump("dump_2");
- ASSERT_DEATH(pmd.CreateAllocatorDump("dump_1"), "");
+ ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+ pmd.CreateAllocatorDump("foo_allocator", MemoryAllocatorDump::kRootHeap);
+ pmd.CreateAllocatorDump("bar_allocator", "heap");
+ ASSERT_DEATH(
+ pmd.CreateAllocatorDump("foo_allocator", MemoryAllocatorDump::kRootHeap),
+ "");
+ ASSERT_DEATH(pmd.CreateAllocatorDump("bar_allocator", "heap"), "");
+ ASSERT_DEATH(pmd.CreateAllocatorDump("", "must_have_allocator_name"), "");
}
#endif
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 0ec5d19..859e8e0 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -9,41 +9,123 @@
#include "base/atomic_sequence_num.h"
#include "base/compiler_specific.h"
#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+#include "base/trace_event/malloc_dump_provider.h"
+#include "base/trace_event/process_memory_maps_dump_provider.h"
+#include "base/trace_event/process_memory_totals_dump_provider.h"
+#elif defined(OS_WIN)
+#include "base/trace_event/winheap_dump_provider_win.h"
+#endif
+
namespace base {
namespace trace_event {
namespace {
+// TODO(primiano): this should be smarter and should do something similar to
+// trace event synthetic delays.
+const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra");
+
MemoryDumpManager* g_instance_for_testing = nullptr;
+const int kDumpIntervalSeconds = 2;
const int kTraceEventNumArgs = 1;
const char* kTraceEventArgNames[] = {"dumps"};
const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
StaticAtomicSequenceNumber g_next_guid;
-const char* DumpPointTypeToString(const DumpPointType& dump_point_type) {
- switch (dump_point_type) {
- case DumpPointType::TASK_BEGIN:
+const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
+ switch (dump_type) {
+ case MemoryDumpType::TASK_BEGIN:
return "TASK_BEGIN";
- case DumpPointType::TASK_END:
+ case MemoryDumpType::TASK_END:
return "TASK_END";
- case DumpPointType::PERIODIC_INTERVAL:
+ case MemoryDumpType::PERIODIC_INTERVAL:
return "PERIODIC_INTERVAL";
- case DumpPointType::EXPLICITLY_TRIGGERED:
+ case MemoryDumpType::EXPLICITLY_TRIGGERED:
return "EXPLICITLY_TRIGGERED";
}
NOTREACHED();
return "UNKNOWN";
}
+// Internal class used to hold details about ProcessMemoryDump requests for the
+// current process.
+// TODO(primiano): In the upcoming CLs, ProcessMemoryDump will become async.
+// and this class will be used to convey more details across PostTask()s.
+class ProcessMemoryDumpHolder
+ : public RefCountedThreadSafe<ProcessMemoryDumpHolder> {
+ public:
+ ProcessMemoryDumpHolder(
+ MemoryDumpRequestArgs req_args,
+ const scoped_refptr<MemoryDumpSessionState>& session_state,
+ MemoryDumpCallback callback)
+ : process_memory_dump(session_state),
+ req_args(req_args),
+ callback(callback),
+ task_runner(MessageLoop::current()->task_runner()),
+ num_pending_async_requests(0) {}
+
+ ProcessMemoryDump process_memory_dump;
+ const MemoryDumpRequestArgs req_args;
+
+ // Callback passed to the initial call to CreateProcessDump().
+ MemoryDumpCallback callback;
+
+ // Thread on which FinalizeDumpAndAddToTrace() should be called, which is the
+ // same that invoked the initial CreateProcessDump().
+ const scoped_refptr<SingleThreadTaskRunner> task_runner;
+
+ // Number of pending ContinueAsyncProcessDump() calls.
+ int num_pending_async_requests;
+
+ private:
+ friend class RefCountedThreadSafe<ProcessMemoryDumpHolder>;
+ virtual ~ProcessMemoryDumpHolder() {}
+ DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpHolder);
+};
+
+void FinalizeDumpAndAddToTrace(
+ const scoped_refptr<ProcessMemoryDumpHolder>& pmd_holder) {
+ DCHECK_EQ(0, pmd_holder->num_pending_async_requests);
+
+ if (!pmd_holder->task_runner->BelongsToCurrentThread()) {
+ pmd_holder->task_runner->PostTask(
+ FROM_HERE, Bind(&FinalizeDumpAndAddToTrace, pmd_holder));
+ return;
+ }
+
+ scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
+ pmd_holder->process_memory_dump.AsValueInto(
+ static_cast<TracedValue*>(event_value.get()));
+ const char* const event_name =
+ MemoryDumpTypeToString(pmd_holder->req_args.dump_type);
+
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ TRACE_EVENT_PHASE_MEMORY_DUMP,
+ TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
+ pmd_holder->req_args.dump_guid, kTraceEventNumArgs, kTraceEventArgNames,
+ kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
+ TRACE_EVENT_FLAG_HAS_ID);
+
+ if (!pmd_holder->callback.is_null()) {
+ pmd_holder->callback.Run(pmd_holder->req_args.dump_guid, true);
+ pmd_holder->callback.Reset();
+ }
+}
+
+void RequestPeriodicGlobalDump() {
+ MemoryDumpManager::GetInstance()->RequestGlobalDump(
+ MemoryDumpType::PERIODIC_INTERVAL);
+}
+
} // namespace
-// TODO(primiano): this should be smarter and should do something similar to
-// trace event synthetic delays.
-const char MemoryDumpManager::kTraceCategory[] =
- TRACE_DISABLED_BY_DEFAULT("memory-dumps");
+// static
+const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory;
// static
MemoryDumpManager* MemoryDumpManager::GetInstance() {
@@ -56,11 +138,17 @@
// static
void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
+ if (instance)
+ instance->skip_core_dumpers_auto_registration_for_testing_ = true;
g_instance_for_testing = instance;
}
MemoryDumpManager::MemoryDumpManager()
- : dump_provider_currently_active_(nullptr), memory_tracing_enabled_(0) {
+ : dump_provider_currently_active_(nullptr),
+ delegate_(nullptr),
+ memory_tracing_enabled_(0),
+ skip_core_dumpers_auto_registration_for_testing_(false) {
+ g_next_guid.GetNext(); // Make sure that first guid is not zero.
}
MemoryDumpManager::~MemoryDumpManager() {
@@ -70,94 +158,176 @@
void MemoryDumpManager::Initialize() {
TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+
+ if (skip_core_dumpers_auto_registration_for_testing_)
+ return;
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+ // Enable the core dump providers.
+ RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
+ RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
+ RegisterDumpProvider(MallocDumpProvider::GetInstance());
+#elif defined(OS_WIN)
+ RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
+#endif
+}
+
+void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
+ AutoLock lock(lock_);
+ DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
+ delegate_ = delegate;
}
void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
AutoLock lock(lock_);
- if (std::find(dump_providers_registered_.begin(),
- dump_providers_registered_.end(),
- mdp) != dump_providers_registered_.end()) {
- return;
- }
- dump_providers_registered_.push_back(mdp);
+ dump_providers_registered_.insert(mdp);
}
void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
AutoLock lock(lock_);
- // Remove from the registered providers list.
- auto it = std::find(dump_providers_registered_.begin(),
- dump_providers_registered_.end(), mdp);
- if (it != dump_providers_registered_.end())
- dump_providers_registered_.erase(it);
+ // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
+ // only if the MDP has specified a thread affinity (via task_runner()) AND
+ // the unregistration happens on the same thread (so the MDP cannot unregister
+ // and DumpInto() at the same time).
+ // Otherwise, it is not possible to guarantee that its unregistration is
+ // race-free. If you hit this DCHECK, your MDP has a bug.
+ DCHECK_IMPLIES(
+ subtle::NoBarrier_Load(&memory_tracing_enabled_),
+ mdp->task_runner() && mdp->task_runner()->BelongsToCurrentThread())
+ << "The MemoryDumpProvider " << mdp->GetFriendlyName() << " attempted to "
+ << "unregister itself in a racy way. Please file a crbug.";
// Remove from the enabled providers list. This is to deal with the case that
// UnregisterDumpProvider is called while the trace is enabled.
- it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
- mdp);
- if (it != dump_providers_enabled_.end())
- dump_providers_enabled_.erase(it);
+ dump_providers_enabled_.erase(mdp);
+ dump_providers_registered_.erase(mdp);
}
-void MemoryDumpManager::RequestDumpPoint(DumpPointType dump_point_type) {
- // TODO(primiano): this will have more logic to coordinate dump points across
- // multiple processes via IPC. See crbug.com/462930.
-
+void MemoryDumpManager::RequestGlobalDump(
+ MemoryDumpType dump_type,
+ const MemoryDumpCallback& callback) {
// Bail out immediately if tracing is not enabled at all.
if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
return;
- // TODO(primiano): Make guid actually unique (cross-process) by hashing it
- // with the PID. See crbug.com/462931 for details.
- const uint64 guid = g_next_guid.GetNext();
- CreateLocalDumpPoint(dump_point_type, guid);
-}
+ const uint64 guid =
+ TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
-void MemoryDumpManager::BroadcastDumpRequest() {
- NOTREACHED(); // TODO(primiano): implement IPC synchronization.
-}
-
-// Creates a dump point for the current process and appends it to the trace.
-void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type,
- uint64 guid) {
- bool did_any_provider_dump = false;
- scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump());
-
- // Serialize dump point generation so that memory dump providers don't have to
- // deal with thread safety.
+ // The delegate_ is supposed to be thread safe, immutable and long lived.
+ // No need to keep the lock after we ensure that a delegate has been set.
+ MemoryDumpManagerDelegate* delegate;
{
AutoLock lock(lock_);
- for (auto it = dump_providers_enabled_.begin();
- it != dump_providers_enabled_.end();) {
- dump_provider_currently_active_ = *it;
- if (dump_provider_currently_active_->DumpInto(pmd.get())) {
- did_any_provider_dump = true;
- ++it;
- } else {
- LOG(ERROR) << "The memory dumper "
- << dump_provider_currently_active_->GetFriendlyName()
- << " failed, possibly due to sandboxing (crbug.com/461788), "
- "disabling it for current process. Try restarting chrome "
- "with the --no-sandbox switch.";
- it = dump_providers_enabled_.erase(it);
- }
- dump_provider_currently_active_ = nullptr;
- }
+ delegate = delegate_;
}
- // Don't create a dump point if all the dumpers failed.
- if (!did_any_provider_dump)
- return;
+ if (delegate) {
+ // The delegate is in charge to coordinate the request among all the
+ // processes and call the CreateLocalDumpPoint on the local process.
+ MemoryDumpRequestArgs args = {guid, dump_type};
+ delegate->RequestGlobalMemoryDump(args, callback);
+ } else if (!callback.is_null()) {
+ callback.Run(guid, false /* success */);
+ }
+}
- scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
- pmd->AsValueInto(static_cast<TracedValue*>(event_value.get()));
- const char* const event_name = DumpPointTypeToString(dump_point_type);
+void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) {
+ RequestGlobalDump(dump_type, MemoryDumpCallback());
+}
- TRACE_EVENT_API_ADD_TRACE_EVENT(
- TRACE_EVENT_PHASE_MEMORY_DUMP,
- TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, guid,
- kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes,
- NULL /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID);
+// Creates a memory dump for the current process and appends it to the trace.
+void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
+ const MemoryDumpCallback& callback) {
+ scoped_refptr<ProcessMemoryDumpHolder> pmd_holder(
+ new ProcessMemoryDumpHolder(args, session_state_, callback));
+ ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
+ bool did_any_provider_dump = false;
+
+ // Iterate over the active dump providers and invoke DumpInto(pmd).
+ // The MDM guarantees linearity (at most one MDP is active within one
+ // process) and thread-safety (MDM enforces the right locking when entering /
+ // leaving the MDP.DumpInto() call). This is to simplify the clients' design
+ // and not let the MDPs worry about locking.
+ // As regards thread affinity, depending on the MDP configuration (see
+ // memory_dump_provider.h), the DumpInto() invocation can happen:
+ // - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
+ // - Posted on MDP.task_runner(), when MDP.task_runner() is set.
+ {
+ AutoLock lock(lock_);
+ for (auto dump_provider_iter = dump_providers_enabled_.begin();
+ dump_provider_iter != dump_providers_enabled_.end();) {
+ // InvokeDumpProviderLocked will remove the MDP from the set if it fails.
+ MemoryDumpProvider* mdp = *dump_provider_iter;
+ ++dump_provider_iter;
+ if (mdp->task_runner()) {
+ // The DumpInto() call must be posted.
+ bool did_post_async_task = mdp->task_runner()->PostTask(
+ FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
+ Unretained(this), Unretained(mdp), pmd_holder));
+ // The thread underlying the TaskRunner might have gone away.
+ if (did_post_async_task)
+ ++pmd_holder->num_pending_async_requests;
+ } else {
+ // Invoke the dump provider synchronously.
+ did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd);
+ }
+ }
+ } // AutoLock
+
+ // If at least one synchronous provider did dump and there are no pending
+ // asynchronous requests, add the dump to the trace and invoke the callback
+ // straight away (FinalizeDumpAndAddToTrace() takes care of the callback).
+ if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0)
+ FinalizeDumpAndAddToTrace(pmd_holder);
+}
+
+// Invokes the MemoryDumpProvider.DumpInto(), taking care of the failsafe logic
+// which disables the dumper when failing (crbug.com/461788).
+bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
+ ProcessMemoryDump* pmd) {
+ lock_.AssertAcquired();
+ dump_provider_currently_active_ = mdp;
+ bool dump_successful = mdp->DumpInto(pmd);
+ dump_provider_currently_active_ = nullptr;
+ if (!dump_successful) {
+ LOG(ERROR) << "The memory dumper " << mdp->GetFriendlyName()
+ << " failed, possibly due to sandboxing (crbug.com/461788), "
+ "disabling it for current process. Try restarting chrome "
+ "with the --no-sandbox switch.";
+ dump_providers_enabled_.erase(mdp);
+ }
+ return dump_successful;
+}
+
+// This is posted to arbitrary threads as a continuation of CreateProcessDump(),
+// when one or more MemoryDumpProvider(s) require the DumpInto() call to happen
+// on a different thread.
+void MemoryDumpManager::ContinueAsyncProcessDump(
+ MemoryDumpProvider* mdp,
+ scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
+ bool should_finalize_dump = false;
+ {
+ // The lock here is to guarantee that different asynchronous dumps on
+ // different threads are still serialized, so that the MemoryDumpProvider
+ // has a consistent view of the |pmd| argument passed.
+ AutoLock lock(lock_);
+ ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
+
+ // Check if the MemoryDumpProvider is still there. It might have been
+ // destroyed and unregistered while hopping threads.
+ if (dump_providers_enabled_.count(mdp))
+ InvokeDumpProviderLocked(mdp, pmd);
+
+ // Finalize the dump appending it to the trace if this was the last
+ // asynchronous request pending.
+ --pmd_holder->num_pending_async_requests;
+ if (pmd_holder->num_pending_async_requests == 0)
+ should_finalize_dump = true;
+ } // AutoLock(lock_)
+
+ if (should_finalize_dump)
+ FinalizeDumpAndAddToTrace(pmd_holder);
}
void MemoryDumpManager::OnTraceLogEnabled() {
@@ -168,19 +338,36 @@
TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
AutoLock lock(lock_);
- if (enabled) {
- dump_providers_enabled_.assign(dump_providers_registered_.begin(),
- dump_providers_registered_.end());
- } else {
+
+ // There is no point starting the tracing without a delegate.
+ if (!enabled || !delegate_) {
dump_providers_enabled_.clear();
+ return;
}
+
+ // Merge the dictionary of allocator attributes from all dump providers
+ // into the session state.
+ session_state_ = new MemoryDumpSessionState();
+ for (const MemoryDumpProvider* mdp : dump_providers_registered_) {
+ session_state_->allocators_attributes_type_info.Update(
+ mdp->allocator_attributes_type_info());
+ }
+ dump_providers_enabled_ = dump_providers_registered_;
subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+
+ if (delegate_->IsCoordinatorProcess()) {
+ periodic_dump_timer_.Start(FROM_HERE,
+ TimeDelta::FromSeconds(kDumpIntervalSeconds),
+ base::Bind(&RequestPeriodicGlobalDump));
+ }
}
void MemoryDumpManager::OnTraceLogDisabled() {
AutoLock lock(lock_);
+ periodic_dump_timer_.Stop();
dump_providers_enabled_.clear();
subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
+ session_state_ = nullptr;
}
} // namespace trace_event
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 04d0135..371a47a 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -8,42 +8,58 @@
#include <vector>
#include "base/atomicops.h"
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "base/trace_event/memory_dump_request_args.h"
#include "base/trace_event/trace_event.h"
namespace base {
namespace trace_event {
-class MemoryDumpProvider;
+namespace {
+class ProcessMemoryDumpHolder;
+}
-// Captures the reason why a dump point is being requested. This is to allow
-// selective enabling of dump points, filtering and post-processing.
-enum class DumpPointType {
- TASK_BEGIN, // Dumping memory at the beginning of a message-loop task.
- TASK_END, // Dumping memory at the ending of a message-loop task.
- PERIODIC_INTERVAL, // Dumping memory at periodic intervals.
- EXPLICITLY_TRIGGERED, // Non maskable dump request.
-};
+class MemoryDumpManagerDelegate;
+class MemoryDumpProvider;
+class ProcessMemoryDump;
+class MemoryDumpSessionState;
// This is the interface exposed to the rest of the codebase to deal with
// memory tracing. The main entry point for clients is represented by
// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
public:
+ static const char* const kTraceCategoryForTesting;
+
static MemoryDumpManager* GetInstance();
// Invoked once per process to register the TraceLog observer.
void Initialize();
+ // See the lifetime and thread-safety requirements on the delegate below in
+ // the |MemoryDumpManagerDelegate| docstring.
+ void SetDelegate(MemoryDumpManagerDelegate* delegate);
+
// MemoryDumpManager does NOT take memory ownership of |mdp|, which is
- // expected to be a singleton.
+ // expected to either be a singleton or unregister itself.
void RegisterDumpProvider(MemoryDumpProvider* mdp);
void UnregisterDumpProvider(MemoryDumpProvider* mdp);
// Requests a memory dump. The dump might happen or not depending on the
// filters and categories specified when enabling tracing.
- void RequestDumpPoint(DumpPointType dump_point_type);
+ // The optional |callback| is executed asynchronously, on an arbitrary thread,
+ // to notify about the completion of the global dump (i.e. after all the
+ // processes have dumped) and its success (true iff all the dumps were
+ // successful).
+ void RequestGlobalDump(MemoryDumpType dump_type,
+ const MemoryDumpCallback& callback);
+
+ // Same as above (still asynchronous), but without callback.
+ void RequestGlobalDump(MemoryDumpType dump_type);
// TraceLog::EnabledStateObserver implementation.
void OnTraceLogEnabled() override;
@@ -55,41 +71,89 @@
return dump_provider_currently_active_;
}
+ // Returns the MemoryDumpSessionState object, which is shared by all the
+ // ProcessMemoryDump and MemoryAllocatorDump instances through all the tracing
+ // session lifetime.
+ const scoped_refptr<MemoryDumpSessionState>& session_state() const {
+ return session_state_;
+ }
+
private:
friend struct DefaultDeleter<MemoryDumpManager>; // For the testing instance.
friend struct DefaultSingletonTraits<MemoryDumpManager>;
+ friend class MemoryDumpManagerDelegate;
friend class MemoryDumpManagerTest;
- static const char kTraceCategory[];
-
static void SetInstanceForTesting(MemoryDumpManager* instance);
MemoryDumpManager();
virtual ~MemoryDumpManager();
- // Broadcasts the dump requests to the other processes.
- void BroadcastDumpRequest();
+ // Internal, used only by MemoryDumpManagerDelegate.
+ // Creates a memory dump for the current process and appends it to the trace.
+ // |callback| will be invoked asynchronously upon completion on the same
+ // thread on which CreateProcessDump() was called.
+ void CreateProcessDump(const MemoryDumpRequestArgs& args,
+ const MemoryDumpCallback& callback);
- // Creates a dump point for the current process and appends it to the trace.
- void CreateLocalDumpPoint(DumpPointType dump_point_type, uint64 guid);
+ bool InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
+ ProcessMemoryDump* pmd);
+ void ContinueAsyncProcessDump(
+ MemoryDumpProvider* mdp,
+ scoped_refptr<ProcessMemoryDumpHolder> pmd_holder);
- std::vector<MemoryDumpProvider*> dump_providers_registered_; // Not owned.
- std::vector<MemoryDumpProvider*> dump_providers_enabled_; // Not owned.
+ hash_set<MemoryDumpProvider*> dump_providers_registered_; // Not owned.
+ hash_set<MemoryDumpProvider*> dump_providers_enabled_; // Not owned.
// TODO(primiano): this is required only until crbug.com/466121 gets fixed.
- MemoryDumpProvider* dump_provider_currently_active_; // Now owned.
+ MemoryDumpProvider* dump_provider_currently_active_; // Not owned.
- // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing
- // down logging while creating a dump point on another thread.
+ // Shared among all the PMDs to keep state scoped to the tracing session.
+ scoped_refptr<MemoryDumpSessionState> session_state_;
+
+ MemoryDumpManagerDelegate* delegate_; // Not owned.
+
+ // Protects from concurrent accesses to the |dump_providers_*| and |delegate_|
+ // to guard against disabling logging while dumping on another thread.
Lock lock_;
- // Optimization to avoid attempting any dump point (i.e. to not walk an empty
+ // Optimization to avoid attempting any memory dump (i.e. to not walk an empty
// dump_providers_enabled_ list) when tracing is not enabled.
subtle::AtomicWord memory_tracing_enabled_;
+ // For time-triggered periodic dumps.
+ RepeatingTimer<MemoryDumpManager> periodic_dump_timer_;
+
+ // Skips the auto-registration of the core dumpers during Initialize().
+ bool skip_core_dumpers_auto_registration_for_testing_;
+
DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
};
+// The delegate is supposed to be long lived (read: a Singleton) and thread
+// safe (i.e. should expect calls from any thread and handle thread hopping).
+class BASE_EXPORT MemoryDumpManagerDelegate {
+ public:
+ virtual void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args,
+ const MemoryDumpCallback& callback) = 0;
+
+ // Determines whether the MemoryDumpManager instance should be the master
+ // (the ones which initiates and coordinates the multiprocess dumps) or not.
+ virtual bool IsCoordinatorProcess() const = 0;
+
+ protected:
+ MemoryDumpManagerDelegate() {}
+ virtual ~MemoryDumpManagerDelegate() {}
+
+ void CreateProcessDump(const MemoryDumpRequestArgs& args,
+ const MemoryDumpCallback& callback) {
+ MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate);
+};
+
} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 65e719f..589c406 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -4,6 +4,11 @@
#include "base/trace_event/memory_dump_manager.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -16,23 +21,46 @@
namespace base {
namespace trace_event {
+// Testing MemoryDumpManagerDelegate which short-circuits dump requests locally
+// instead of performing IPC dances.
+class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate {
+ public:
+ void RequestGlobalMemoryDump(
+ const base::trace_event::MemoryDumpRequestArgs& args,
+ const MemoryDumpCallback& callback) override {
+ CreateProcessDump(args, callback);
+ }
+
+ bool IsCoordinatorProcess() const override { return false; }
+};
+
class MemoryDumpManagerTest : public testing::Test {
public:
void SetUp() override {
+ message_loop_.reset(new MessageLoop());
mdm_.reset(new MemoryDumpManager());
MemoryDumpManager::SetInstanceForTesting(mdm_.get());
ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance());
MemoryDumpManager::GetInstance()->Initialize();
+ MemoryDumpManager::GetInstance()->SetDelegate(&delegate_);
}
void TearDown() override {
MemoryDumpManager::SetInstanceForTesting(nullptr);
mdm_.reset();
+ message_loop_.reset();
TraceLog::DeleteForTesting();
}
+ void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner,
+ Closure closure,
+ uint64 dump_guid,
+ bool success) {
+ task_runner->PostTask(FROM_HERE, closure);
+ }
+
protected:
- const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
+ const char* kTraceCategory = MemoryDumpManager::kTraceCategoryForTesting;
void EnableTracing(const char* category) {
TraceLog::GetInstance()->SetEnabled(
@@ -44,15 +72,29 @@
scoped_ptr<MemoryDumpManager> mdm_;
private:
+ scoped_ptr<MessageLoop> message_loop_;
+ MemoryDumpManagerDelegateForTesting delegate_;
+
// We want our singleton torn down after each test.
ShadowingAtExitManager at_exit_manager_;
};
class MockDumpProvider : public MemoryDumpProvider {
public:
+ MockDumpProvider() {}
+
+ explicit MockDumpProvider(
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+ : MemoryDumpProvider(task_runner) {}
+
+ // Ctor for the SharedSessionState test.
+ explicit MockDumpProvider(const std::string& id) {
+ DeclareAllocatorAttribute("allocator" + id, "attr" + id, "type" + id);
+ }
+
MOCK_METHOD1(DumpInto, bool(ProcessMemoryDump* pmd));
- // DumpInto() override for the ActiveDumpProviderConsistency test,
+ // DumpInto() override for the ActiveDumpProviderConsistency test.
bool DumpIntoAndCheckDumpProviderCurrentlyActive(ProcessMemoryDump* pmd) {
EXPECT_EQ(
this,
@@ -60,6 +102,22 @@
return true;
}
+ // DumpInto() override for the RespectTaskRunnerAffinity test.
+ bool DumpIntoAndCheckTaskRunner(ProcessMemoryDump* pmd) {
+ EXPECT_TRUE(task_runner()->RunsTasksOnCurrentThread());
+ return true;
+ }
+
+ // DumpInto() override for the SharedSessionState test.
+ bool DumpIntoAndCheckSessionState(ProcessMemoryDump* pmd) {
+ EXPECT_TRUE(pmd->session_state());
+ const auto& attrs_type_info =
+ pmd->session_state()->allocators_attributes_type_info;
+ EXPECT_TRUE(attrs_type_info.Exists("allocator1", "attr1"));
+ EXPECT_TRUE(attrs_type_info.Exists("allocator2", "attr2"));
+ return true;
+ }
+
const char* GetFriendlyName() const override { return "MockDumpProvider"; }
};
@@ -70,7 +128,7 @@
// Check that the dumper is not called if the memory category is not enabled.
EnableTracing("foo-and-bar-but-not-memory");
EXPECT_CALL(mdp, DumpInto(_)).Times(0);
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Now repeat enabling the memory category and check that the dumper is
@@ -78,7 +136,7 @@
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp, DumpInto(_)).Times(3).WillRepeatedly(Return(true));
for (int i = 0; i < 3; ++i)
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
mdm_->UnregisterDumpProvider(&mdp);
@@ -86,21 +144,24 @@
// Finally check the unregister logic (no calls to the mdp after unregister).
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp, DumpInto(_)).Times(0);
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
TraceLog::GetInstance()->SetDisabled();
}
-TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
- MockDumpProvider mdp;
- mdm_->RegisterDumpProvider(&mdp);
+TEST_F(MemoryDumpManagerTest, SharedSessionState) {
+ MockDumpProvider mdp1("1"); // Will declare an allocator property "attr1".
+ MockDumpProvider mdp2("2"); // Will declare an allocator property "attr2".
+ mdm_->RegisterDumpProvider(&mdp1);
+ mdm_->RegisterDumpProvider(&mdp2);
EnableTracing(kTraceCategory);
- EXPECT_CALL(mdp, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(2).WillRepeatedly(
+ Invoke(&mdp1, &MockDumpProvider::DumpIntoAndCheckSessionState));
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(2).WillRepeatedly(
+ Invoke(&mdp2, &MockDumpProvider::DumpIntoAndCheckSessionState));
- mdm_->UnregisterDumpProvider(&mdp);
- EXPECT_CALL(mdp, DumpInto(_)).Times(0);
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ for (int i = 0; i < 2; ++i)
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
}
@@ -114,7 +175,7 @@
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Invert: enable mdp1 and disable mdp2.
@@ -123,7 +184,7 @@
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Enable both mdp1 and mdp2.
@@ -131,7 +192,66 @@
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+}
+
+// Checks that the MemoryDumpManager respects the thread affinity when a
+// MemoryDumpProvider specifies a task_runner(). The test starts creating 8
+// threads and registering a MemoryDumpProvider on each of them. At each
+// iteration, one thread is removed, to check the live unregistration logic.
+TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
+ const uint32 kNumInitialThreads = 8;
+
+ ScopedVector<Thread> threads;
+ ScopedVector<MockDumpProvider> mdps;
+
+ // Create the threads and setup the expectations. Given that at each iteration
+ // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
+ // invoked a number of times equal to its index.
+ for (uint32 i = kNumInitialThreads; i > 0; --i) {
+ threads.push_back(new Thread("test thread"));
+ threads.back()->Start();
+ mdps.push_back(new MockDumpProvider(threads.back()->task_runner()));
+ MockDumpProvider* mdp = mdps.back();
+ mdm_->RegisterDumpProvider(mdp);
+ EXPECT_CALL(*mdp, DumpInto(_))
+ .Times(i)
+ .WillRepeatedly(
+ Invoke(mdp, &MockDumpProvider::DumpIntoAndCheckTaskRunner));
+ }
+
+ EnableTracing(kTraceCategory);
+
+ while (!threads.empty()) {
+ {
+ RunLoop run_loop;
+ MemoryDumpCallback callback =
+ Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this),
+ MessageLoop::current()->task_runner(), run_loop.QuitClosure());
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, callback);
+ // This nested message loop (|run_loop|) will be quit if and only if
+ // the RequestGlobalDump callback is invoked.
+ run_loop.Run();
+ }
+
+ // Unregister a MDP and destroy one thread at each iteration to check the
+ // live unregistration logic. The unregistration needs to happen on the same
+ // thread the MDP belongs to.
+ {
+ RunLoop run_loop;
+ Closure unregistration =
+ Bind(&MemoryDumpManager::UnregisterDumpProvider,
+ Unretained(mdm_.get()), Unretained(mdps.back()));
+ threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+ mdps.pop_back();
+ threads.back()->Stop();
+ threads.pop_back();
+ }
+
DisableTracing();
}
@@ -148,11 +268,11 @@
EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
}
@@ -177,8 +297,8 @@
.WillRepeatedly(Invoke(
&mdp2,
&MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive));
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
- mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
+ mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
DisableTracing();
}
diff --git a/base/trace_event/memory_dump_provider.cc b/base/trace_event/memory_dump_provider.cc
index 9518461..a2d3889 100644
--- a/base/trace_event/memory_dump_provider.cc
+++ b/base/trace_event/memory_dump_provider.cc
@@ -4,7 +4,7 @@
#include "base/trace_event/memory_dump_provider.h"
-#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
namespace base {
namespace trace_event {
@@ -12,15 +12,20 @@
MemoryDumpProvider::MemoryDumpProvider() {
}
+MemoryDumpProvider::MemoryDumpProvider(
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+ : task_runner_(task_runner) {
+}
+
MemoryDumpProvider::~MemoryDumpProvider() {
}
void MemoryDumpProvider::DeclareAllocatorAttribute(
- const MemoryAllocatorDeclaredAttribute& attr) {
- DCHECK_EQ(0u, allocator_attributes_.count(attr.name))
- << "Allocator attribute " << attr.name << " already declared for dumper "
- << GetFriendlyName();
- allocator_attributes_[attr.name] = attr;
+ const std::string& allocator_name,
+ const std::string& attribute_name,
+ const std::string& attribute_type) {
+ allocator_attributes_type_info_.Set(
+ allocator_name, attribute_name, attribute_type);
}
} // namespace trace_event
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
index 5cc3a6e..9ec7ad9 100644
--- a/base/trace_event/memory_dump_provider.h
+++ b/base/trace_event/memory_dump_provider.h
@@ -6,9 +6,13 @@
#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
#include "base/base_export.h"
-#include "base/trace_event/memory_allocator_attributes.h"
+#include "base/memory/ref_counted.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
namespace base {
+
+class SingleThreadTaskRunner;
+
namespace trace_event {
class ProcessMemoryDump;
@@ -16,27 +20,46 @@
// The contract interface that memory dump providers must implement.
class BASE_EXPORT MemoryDumpProvider {
public:
- // Called by the MemoryDumpManager when generating dump points.
+ // Called by the MemoryDumpManager when generating memory dumps.
// Returns: true if the |pmd| was successfully populated, false otherwise.
virtual bool DumpInto(ProcessMemoryDump* pmd) = 0;
virtual const char* GetFriendlyName() const = 0;
- const MemoryAllocatorDeclaredAttributes& allocator_attributes() const {
- return allocator_attributes_;
+ const MemoryAllocatorAttributesTypeInfo& allocator_attributes_type_info()
+ const {
+ return allocator_attributes_type_info_;
+ }
+
+ // The dump provider can specify an optional thread affinity (in its
+ // base constructor call). If |task_runner| is non empty, all the calls to
+ // DumpInto are guaranteed to be posted to that TaskRunner.
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner() const {
+ return task_runner_;
}
protected:
+ // Default ctor: the MDP is not bound to any thread (must be a singleton).
MemoryDumpProvider();
+
+ // Use this ctor to ensure that DumpInto() is called always on the same thread
+ // specified by |task_runner|.
+ explicit MemoryDumpProvider(
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner);
+
virtual ~MemoryDumpProvider();
- void DeclareAllocatorAttribute(const MemoryAllocatorDeclaredAttribute& attr);
+ void DeclareAllocatorAttribute(const std::string& allocator_name,
+ const std::string& attribute_name,
+ const std::string& attribute_type);
private:
- // The map (attribute name -> type) that specifies the semantic of the
- // extra attributes that the MemoryAllocatorDump(s) produced by this
- // MemoryDumpProvider will have.
- MemoryAllocatorDeclaredAttributes allocator_attributes_;
+ // A map of attributes types (declared through DeclareAllocatorAttribute())
+ // emitted by this allocator dumper.
+ MemoryAllocatorAttributesTypeInfo allocator_attributes_type_info_;
+
+ // (Optional) TaskRunner on which the DumpInfo call should be posted.
+ scoped_refptr<SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
};
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h
new file mode 100644
index 0000000..4fb0335
--- /dev/null
+++ b/base/trace_event/memory_dump_request_args.h
@@ -0,0 +1,41 @@
+// 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 BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
+
+// This file defines the types and structs used to issue memory dump requests.
+// These are also used in the IPCs for coordinating inter-process memory dumps.
+
+#include "base/base_export.h"
+#include "base/callback.h"
+
+namespace base {
+namespace trace_event {
+
+// Captures the reason why a memory dump is being requested. This is to allow
+// selective enabling of dumps, filtering and post-processing.
+enum class MemoryDumpType {
+ TASK_BEGIN, // Dumping memory at the beginning of a message-loop task.
+ TASK_END, // Dumping memory at the ending of a message-loop task.
+ PERIODIC_INTERVAL, // Dumping memory at periodic intervals.
+ EXPLICITLY_TRIGGERED, // Non maskable dump request.
+ LAST = EXPLICITLY_TRIGGERED // For IPC macros.
+};
+
+using MemoryDumpCallback = Callback<void(uint64 dump_guid, bool success)>;
+
+struct BASE_EXPORT MemoryDumpRequestArgs {
+ // Globally unique identifier. In multi-process dumps, all processes issue a
+ // local dump with the same guid. This allows the trace importers to
+ // reconstruct the global dump.
+ uint64 dump_guid;
+
+ MemoryDumpType dump_type;
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
diff --git a/base/trace_event/memory_dump_session_state.cc b/base/trace_event/memory_dump_session_state.cc
new file mode 100644
index 0000000..433ac14
--- /dev/null
+++ b/base/trace_event/memory_dump_session_state.cc
@@ -0,0 +1,17 @@
+// 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/trace_event/memory_dump_session_state.h"
+
+namespace base {
+namespace trace_event {
+
+MemoryDumpSessionState::MemoryDumpSessionState() {
+}
+
+MemoryDumpSessionState::~MemoryDumpSessionState() {
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/memory_dump_session_state.h b/base/trace_event/memory_dump_session_state.h
new file mode 100644
index 0000000..38a6fe2
--- /dev/null
+++ b/base/trace_event/memory_dump_session_state.h
@@ -0,0 +1,31 @@
+// 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 BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/memory/ref_counted.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
+
+namespace base {
+namespace trace_event {
+
+class BASE_EXPORT MemoryDumpSessionState
+ : public RefCountedThreadSafe<MemoryDumpSessionState> {
+ public:
+ MemoryDumpSessionState();
+ MemoryAllocatorAttributesTypeInfo allocators_attributes_type_info;
+
+ private:
+ friend class RefCountedThreadSafe<MemoryDumpSessionState>;
+ ~MemoryDumpSessionState();
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
index bbca36c..836d6ae 100644
--- a/base/trace_event/process_memory_dump.cc
+++ b/base/trace_event/process_memory_dump.cc
@@ -10,31 +10,32 @@
namespace base {
namespace trace_event {
-ProcessMemoryDump::ProcessMemoryDump()
- : has_process_totals_(false), has_process_mmaps_(false) {
+ProcessMemoryDump::ProcessMemoryDump(
+ const scoped_refptr<MemoryDumpSessionState>& session_state)
+ : has_process_totals_(false),
+ has_process_mmaps_(false),
+ session_state_(session_state) {
}
ProcessMemoryDump::~ProcessMemoryDump() {
}
MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
- const std::string& name) {
- return CreateAllocatorDump(name, nullptr);
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
- const std::string& name,
- MemoryAllocatorDump* parent) {
- DCHECK_EQ(0ul, allocator_dumps_.count(name));
- MemoryAllocatorDump* mad = new MemoryAllocatorDump(name, parent);
+ const std::string& allocator_name,
+ const std::string& heap_name) {
+ MemoryAllocatorDump* mad =
+ new MemoryAllocatorDump(allocator_name, heap_name, this);
+ DCHECK_EQ(0ul, allocator_dumps_.count(mad->GetAbsoluteName()));
allocator_dumps_storage_.push_back(mad);
- allocator_dumps_[name] = mad;
+ allocator_dumps_[mad->GetAbsoluteName()] = mad;
return mad;
}
MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump(
- const std::string& name) const {
- auto it = allocator_dumps_.find(name);
+ const std::string& allocator_name,
+ const std::string& heap_name) const {
+ auto it = allocator_dumps_.find(
+ MemoryAllocatorDump::GetAbsoluteName(allocator_name, heap_name));
return it == allocator_dumps_.end() ? nullptr : it->second;
}
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h
index df6cc82..bd9c543 100644
--- a/base/trace_event/process_memory_dump.h
+++ b/base/trace_event/process_memory_dump.h
@@ -8,8 +8,10 @@
#include "base/base_export.h"
#include "base/containers/hash_tables.h"
#include "base/containers/small_map.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_maps.h"
#include "base/trace_event/process_memory_totals.h"
@@ -18,19 +20,22 @@
class ConvertableToTraceFormat;
class MemoryDumpManager;
+class MemoryDumpSessionState;
// ProcessMemoryDump is as a strongly typed container which enforces the data
-// model for each memory dump point and holds the dumps produced by the
+// model for each memory dump and holds the dumps produced by the
// MemoryDumpProvider(s) for a specific process.
// At trace generation time (i.e. when AsValue() is called), ProcessMemoryDump
// will compose a key-value dictionary of the various dumps obtained at trace
// dump point time.
class BASE_EXPORT ProcessMemoryDump {
public:
+ // Maps allocator dumps absolute names (allocator_name/heap/subheap) to
+ // MemoryAllocatorDump instances.
using AllocatorDumpsMap =
SmallMap<hash_map<std::string, MemoryAllocatorDump*>>;
- ProcessMemoryDump();
+ ProcessMemoryDump(const scoped_refptr<MemoryDumpSessionState>& session_state);
~ProcessMemoryDump();
// Called at trace generation time to populate the TracedValue.
@@ -45,20 +50,34 @@
void set_has_process_mmaps() { has_process_mmaps_ = true; }
// Creates a new MemoryAllocatorDump with the given name and returns the
- // empty object back to the caller. The |name| must be unique in the dump.
- // ProcessMemoryDump handles the memory ownership of the created object.
- // |parent| can be used to specify a hierarchical relationship of the
- // allocator dumps.
- MemoryAllocatorDump* CreateAllocatorDump(const std::string& name);
- MemoryAllocatorDump* CreateAllocatorDump(const std::string& name,
- MemoryAllocatorDump* parent);
+ // empty object back to the caller.
+ // Arguments:
+ // allocator_name: a name that univocally identifies allocator dumps
+ // produced by this provider. It acts as a type w.r.t. the allocator
+ // attributes, in the sense that all the MAD with the same allocator_name
+ // are expected to have the same attributes.
+ // heap_name, either:
+ // - kRootHeap: if the allocator has only one default heap.
+ // - a string identifing a heap name (e.g., isolate1, isolate2 ...). It is
+ // possible to specify nesting by using a path-like string (e.g.,
+ // isolate1/heap_spaceX, isolate1/heap_spaceY, isolate2/heap_spaceX).
+ // The tuple (|allocator_name|, |heap_name|) is unique inside a PMD.
+ // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps.
+ MemoryAllocatorDump* CreateAllocatorDump(const std::string& allocator_name,
+ const std::string& heap_name);
- // Returns a MemoryAllocatorDump given its name or nullptr if not found.
- MemoryAllocatorDump* GetAllocatorDump(const std::string& name) const;
+ // Looks up a MemoryAllocatorDump given its allocator and heap names, or
+ // nullptr if not found.
+ MemoryAllocatorDump* GetAllocatorDump(const std::string& allocator_name,
+ const std::string& heap_name) const;
// Returns the map of the MemoryAllocatorDumps added to this dump.
const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; }
+ const scoped_refptr<MemoryDumpSessionState>& session_state() const {
+ return session_state_;
+ }
+
private:
ProcessMemoryTotals process_totals_;
bool has_process_totals_;
@@ -66,13 +85,14 @@
ProcessMemoryMaps process_mmaps_;
bool has_process_mmaps_;
- // A maps of "allocator_name" -> MemoryAllocatorDump populated by
- // allocator dump providers.
AllocatorDumpsMap allocator_dumps_;
// ProcessMemoryDump handles the memory ownership of all its belongings.
ScopedVector<MemoryAllocatorDump> allocator_dumps_storage_;
+ // State shared among all PMDs instances created in a given trace session.
+ scoped_refptr<MemoryDumpSessionState> session_state_;
+
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
};
diff --git a/base/trace_event/process_memory_maps_dump_provider_unittest.cc b/base/trace_event/process_memory_maps_dump_provider_unittest.cc
index 0bf81ac..2ce2504 100644
--- a/base/trace_event/process_memory_maps_dump_provider_unittest.cc
+++ b/base/trace_event/process_memory_maps_dump_provider_unittest.cc
@@ -114,7 +114,7 @@
auto pmmdp = ProcessMemoryMapsDumpProvider::GetInstance();
// Emulate a non-existent /proc/self/smaps.
- ProcessMemoryDump pmd_invalid;
+ ProcessMemoryDump pmd_invalid(nullptr /* session_state */);
std::ifstream non_existent_file("/tmp/does-not-exist");
ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &non_existent_file;
CHECK_EQ(false, non_existent_file.good());
@@ -129,7 +129,7 @@
ASSERT_FALSE(pmd_invalid.has_process_mmaps());
// Parse the 1st smaps file.
- ProcessMemoryDump pmd_1;
+ ProcessMemoryDump pmd_1(nullptr /* session_state */);
std::istringstream test_smaps_1(kTestSmaps1);
ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &test_smaps_1;
pmmdp->DumpInto(&pmd_1);
@@ -154,7 +154,7 @@
EXPECT_EQ((60 + 8) * 1024UL, regions_1[1].byte_stats_private_resident);
// Parse the 2nd smaps file.
- ProcessMemoryDump pmd_2;
+ ProcessMemoryDump pmd_2(nullptr /* session_state */);
std::istringstream test_smaps_2(kTestSmaps2);
ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &test_smaps_2;
pmmdp->DumpInto(&pmd_2);
diff --git a/base/trace_event/process_memory_totals_dump_provider_unittest.cc b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
index 372db63..ffaf177 100644
--- a/base/trace_event/process_memory_totals_dump_provider_unittest.cc
+++ b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
@@ -13,8 +13,8 @@
TEST(ProcessMemoryTotalsDumpProviderTest, DumpRSS) {
auto pmtdp = ProcessMemoryTotalsDumpProvider::GetInstance();
- scoped_ptr<ProcessMemoryDump> pmd_before(new ProcessMemoryDump());
- scoped_ptr<ProcessMemoryDump> pmd_after(new ProcessMemoryDump());
+ scoped_ptr<ProcessMemoryDump> pmd_before(new ProcessMemoryDump(nullptr));
+ scoped_ptr<ProcessMemoryDump> pmd_after(new ProcessMemoryDump(nullptr));
ProcessMemoryTotalsDumpProvider::rss_bytes_for_testing = 1024;
pmtdp->DumpInto(pmd_before.get());
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi
index ca6c076..9bbd172 100644
--- a/base/trace_event/trace_event.gypi
+++ b/base/trace_event/trace_event.gypi
@@ -4,13 +4,19 @@
{
'variables': {
'trace_event_sources' : [
- 'trace_event/memory_allocator_attributes.h',
+ 'trace_event/java_heap_dump_provider_android.cc',
+ 'trace_event/java_heap_dump_provider_android.h',
+ 'trace_event/memory_allocator_attributes_type_info.cc',
+ 'trace_event/memory_allocator_attributes_type_info.h',
'trace_event/memory_allocator_dump.cc',
'trace_event/memory_allocator_dump.h',
'trace_event/memory_dump_manager.cc',
'trace_event/memory_dump_manager.h',
'trace_event/memory_dump_provider.cc',
'trace_event/memory_dump_provider.h',
+ 'trace_event/memory_dump_request_args.h',
+ 'trace_event/memory_dump_session_state.cc',
+ 'trace_event/memory_dump_session_state.h',
'trace_event/process_memory_dump.cc',
'trace_event/process_memory_dump.h',
'trace_event/process_memory_maps.cc',
@@ -25,6 +31,8 @@
'trace_event/trace_event_android.cc',
'trace_event/trace_event_argument.cc',
'trace_event/trace_event_argument.h',
+ 'trace_event/trace_event_etw_export_win.cc',
+ 'trace_event/trace_event_etw_export_win.h',
'trace_event/trace_event_impl.cc',
'trace_event/trace_event_impl.h',
'trace_event/trace_event_impl_constants.cc',
@@ -36,8 +44,19 @@
'trace_event/trace_event_system_stats_monitor.h',
'trace_event/trace_event_win.cc',
'trace_event/trace_event_win.h',
+ 'trace_event/winheap_dump_provider_win.cc',
+ 'trace_event/winheap_dump_provider_win.h',
+ ],
+ 'conditions': [
+ ['OS == "linux" or OS == "android"', {
+ 'trace_event_sources': [
+ 'trace_event/malloc_dump_provider.cc',
+ 'trace_event/malloc_dump_provider.h',
+ ],
+ }],
],
'trace_event_test_sources' : [
+ 'trace_event/memory_allocator_attributes_type_info_unittest.cc',
'trace_event/memory_allocator_dump_unittest.cc',
'trace_event/memory_dump_manager_unittest.cc',
'trace_event/process_memory_maps_dump_provider_unittest.cc',
@@ -48,6 +67,7 @@
'trace_event/trace_event_system_stats_monitor_unittest.cc',
'trace_event/trace_event_unittest.cc',
'trace_event/trace_event_win_unittest.cc',
+ 'trace_event/winheap_dump_provider_win_unittest.cc',
],
},
}
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 1bf9429..e0249f5 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -144,11 +144,11 @@
// class MyData : public base::trace_event::ConvertableToTraceFormat {
// public:
// MyData() {}
-// virtual void AppendAsTraceFormat(std::string* out) const override {
+// void AppendAsTraceFormat(std::string* out) const override {
// out->append("{\"foo\":1}");
// }
// private:
-// virtual ~MyData() {}
+// ~MyData() override {}
// DISALLOW_COPY_AND_ASSIGN(MyData);
// };
//
@@ -601,6 +601,12 @@
TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
static_cast<int>(base::PlatformThread::CurrentId()), \
timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, \
+ name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ static_cast<int>(base::PlatformThread::CurrentId()), \
+ timestamp, TRACE_EVENT_FLAG_COPY)
// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
// category is not enabled, then this does nothing. The |name| and |id| must
@@ -828,9 +834,10 @@
category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
- UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
- (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
- base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
+ UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
+ (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
+ base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK | \
+ base::trace_event::TraceLog::ENABLED_FOR_ETW_EXPORT))
// Macro to efficiently determine if a given category group is enabled.
#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
new file mode 100644
index 0000000..f7f9ecc
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -0,0 +1,239 @@
+// 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/trace_event/trace_event_etw_export_win.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_impl.h"
+
+// The GetProcAddress technique is borrowed from
+// https://github.com/randomascii/main/tree/master/xperf/ETWProviders
+//
+// EVNTAPI is used in evntprov.h which is included by chrome_events_win.h.
+// We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can
+// implement these functions locally instead of using the import library, and
+// can therefore still run on Windows XP.
+#define EVNTAPI __stdcall
+// Include the event register/write/unregister macros compiled from the manifest
+// file. Note that this includes evntprov.h which requires a Vista+ Windows SDK.
+//
+// In SHARED_INTERMEDIATE_DIR.
+#include "base/trace_event/etw_manifest/chrome_events_win.h" // NOLINT
+
+namespace {
+// Typedefs for use with GetProcAddress
+typedef ULONG(__stdcall* tEventRegister)(LPCGUID ProviderId,
+ PENABLECALLBACK EnableCallback,
+ PVOID CallbackContext,
+ PREGHANDLE RegHandle);
+typedef ULONG(__stdcall* tEventWrite)(REGHANDLE RegHandle,
+ PCEVENT_DESCRIPTOR EventDescriptor,
+ ULONG UserDataCount,
+ PEVENT_DATA_DESCRIPTOR UserData);
+typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
+
+tEventRegister EventRegisterProc = nullptr;
+tEventWrite EventWriteProc = nullptr;
+tEventUnregister EventUnregisterProc = nullptr;
+} // namespace
+
+// Redirector function for EventRegister. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventRegister(LPCGUID ProviderId,
+ PENABLECALLBACK EnableCallback,
+ PVOID CallbackContext,
+ PREGHANDLE RegHandle) {
+ if (EventRegisterProc)
+ return EventRegisterProc(ProviderId, EnableCallback, CallbackContext,
+ RegHandle);
+ return 0;
+}
+
+// Redirector function for EventWrite. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventWrite(REGHANDLE RegHandle,
+ PCEVENT_DESCRIPTOR EventDescriptor,
+ ULONG UserDataCount,
+ PEVENT_DATA_DESCRIPTOR UserData) {
+ if (EventWriteProc)
+ return EventWriteProc(RegHandle, EventDescriptor, UserDataCount, UserData);
+ return 0;
+}
+
+// Redirector function for EventUnregister. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
+ if (EventUnregisterProc)
+ return EventUnregisterProc(RegHandle);
+ return 0;
+}
+
+namespace base {
+namespace trace_event {
+
+TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
+ // Find Advapi32.dll. This should always succeed.
+ HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
+ if (AdvapiDLL) {
+ // Try to find the ETW functions. This will fail on XP.
+ EventRegisterProc = reinterpret_cast<tEventRegister>(
+ ::GetProcAddress(AdvapiDLL, "EventRegister"));
+ EventWriteProc = reinterpret_cast<tEventWrite>(
+ ::GetProcAddress(AdvapiDLL, "EventWrite"));
+ EventUnregisterProc = reinterpret_cast<tEventUnregister>(
+ ::GetProcAddress(AdvapiDLL, "EventUnregister"));
+
+ // Register the ETW provider. If registration fails then the event logging
+ // calls will fail (on XP this call will do nothing).
+ EventRegisterChrome();
+ }
+}
+
+TraceEventETWExport::~TraceEventETWExport() {
+ EventUnregisterChrome();
+}
+
+// static
+TraceEventETWExport* TraceEventETWExport::GetInstance() {
+ return Singleton<TraceEventETWExport,
+ StaticMemorySingletonTraits<TraceEventETWExport>>::get();
+}
+
+// static
+void TraceEventETWExport::EnableETWExport() {
+ GetInstance()->ETWExportEnabled_ = true;
+}
+
+// static
+void TraceEventETWExport::DisableETWExport() {
+ GetInstance()->ETWExportEnabled_ = false;
+}
+
+// static
+void TraceEventETWExport::AddEvent(
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ const scoped_refptr<ConvertableToTraceFormat>* convertable_values) {
+ // We bail early in case exporting is disabled or no consumer is listening.
+ if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
+ return;
+
+ std::string phase_string;
+ switch (phase) {
+ case TRACE_EVENT_PHASE_BEGIN:
+ phase_string = "Begin";
+ break;
+ case TRACE_EVENT_PHASE_END:
+ phase_string = "End";
+ break;
+ case TRACE_EVENT_PHASE_COMPLETE:
+ phase_string = "Complete";
+ break;
+ case TRACE_EVENT_PHASE_INSTANT:
+ phase_string = "Instant";
+ break;
+ case TRACE_EVENT_PHASE_ASYNC_BEGIN:
+ phase_string = "Async Begin";
+ break;
+ case TRACE_EVENT_PHASE_ASYNC_STEP_INTO:
+ phase_string = "Async Step Into";
+ break;
+ case TRACE_EVENT_PHASE_ASYNC_STEP_PAST:
+ phase_string = "Async Step Past";
+ break;
+ case TRACE_EVENT_PHASE_ASYNC_END:
+ phase_string = "Async End";
+ break;
+ case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN:
+ phase_string = "Nestable Async Begin";
+ break;
+ case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END:
+ phase_string = "Nestable Async End";
+ break;
+ case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT:
+ phase_string = "Nestable Async Instant";
+ break;
+ case TRACE_EVENT_PHASE_FLOW_BEGIN:
+ phase_string = "Phase Flow Begin";
+ break;
+ case TRACE_EVENT_PHASE_FLOW_STEP:
+ phase_string = "Phase Flow Step";
+ break;
+ case TRACE_EVENT_PHASE_FLOW_END:
+ phase_string = "Phase Flow End";
+ break;
+ case TRACE_EVENT_PHASE_METADATA:
+ phase_string = "Phase Metadata";
+ break;
+ case TRACE_EVENT_PHASE_COUNTER:
+ phase_string = "Phase Counter";
+ break;
+ case TRACE_EVENT_PHASE_SAMPLE:
+ phase_string = "Phase Sample";
+ break;
+ case TRACE_EVENT_PHASE_CREATE_OBJECT:
+ phase_string = "Phase Create Object";
+ break;
+ case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT:
+ phase_string = "Phase Snapshot Object";
+ break;
+ case TRACE_EVENT_PHASE_DELETE_OBJECT:
+ phase_string = "Phase Delete Object";
+ break;
+ default:
+ phase_string.push_back(phase);
+ break;
+ }
+
+ std::string arg_values_string[3];
+ for (int i = 0; i < num_args; i++) {
+ if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
+ convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
+ } else {
+ TraceEvent::TraceValue trace_event;
+ trace_event.as_uint = arg_values[i];
+ TraceEvent::AppendValueAsJSON(arg_types[i], trace_event,
+ arg_values_string + i);
+ }
+ }
+
+ EventWriteChromeEvent(
+ name, phase_string.c_str(), num_args > 0 ? arg_names[0] : "",
+ arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "",
+ arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "",
+ arg_values_string[2].c_str());
+}
+
+// static
+void TraceEventETWExport::AddCustomEvent(const char* name,
+ char const* phase,
+ const char* arg_name_1,
+ const char* arg_value_1,
+ const char* arg_name_2,
+ const char* arg_value_2,
+ const char* arg_name_3,
+ const char* arg_value_3) {
+ if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
+ return;
+
+ EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2,
+ arg_value_2, arg_name_3, arg_value_3);
+}
+
+void TraceEventETWExport::Resurrect() {
+ StaticMemorySingletonTraits<TraceEventETWExport>::Resurrect();
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
new file mode 100644
index 0000000..0a551c3
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -0,0 +1,73 @@
+// 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.
+
+// This file contains the Windows-specific exporting to ETW.
+#ifndef BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+#define BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+
+#include "base/base_export.h"
+#include "base/trace_event/trace_event_impl.h"
+
+// Fwd.
+template <typename Type>
+struct StaticMemorySingletonTraits;
+
+namespace base {
+namespace trace_event {
+
+class BASE_EXPORT TraceEventETWExport {
+ public:
+ ~TraceEventETWExport();
+
+ // Retrieves the singleton.
+ // Note that this may return NULL post-AtExit processing.
+ static TraceEventETWExport* GetInstance();
+
+ // Enables/disables exporting of events to ETW. If disabled,
+ // AddEvent and AddCustomEvent will simply return when called.
+ static void EnableETWExport();
+ static void DisableETWExport();
+
+ static bool isETWExportEnabled() { return GetInstance()->ETWExportEnabled_; }
+
+ // Exports an event to ETW. This is mainly used in
+ // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
+ static void AddEvent(
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ const scoped_refptr<ConvertableToTraceFormat>* convertable_values);
+
+ // Exports an event to ETW. This should be used when exporting an event only
+ // to ETW. Supports three arguments to be passed to ETW.
+ // TODO(georgesak): Allow different providers.
+ static void AddCustomEvent(const char* name,
+ char const* phase,
+ const char* arg_name_1,
+ const char* arg_value_1,
+ const char* arg_name_2,
+ const char* arg_value_2,
+ const char* arg_name_3,
+ const char* arg_value_3);
+
+ void Resurrect();
+
+ private:
+ bool ETWExportEnabled_;
+ // Ensure only the provider can construct us.
+ friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
+ TraceEventETWExport();
+
+ DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 72b46f9..cbeeeab 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -5,12 +5,12 @@
#include "base/trace_event/trace_event_impl.h"
#include <algorithm>
+#include <cmath>
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
-#include "base/float_util.h"
#include "base/format_macros.h"
#include "base/json/string_escape.h"
#include "base/lazy_instance.h"
@@ -30,11 +30,13 @@
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_id_name_manager.h"
+#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_synthetic_delay.h"
#if defined(OS_WIN)
+#include "base/trace_event/trace_event_etw_export_win.h"
#include "base/trace_event/trace_event_win.h"
#endif
@@ -73,7 +75,7 @@
512000000 / kTraceBufferChunkSize;
const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize;
const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4;
-const size_t kTraceEventBatchChunks = 1000 / kTraceBufferChunkSize;
+const size_t kTraceEventBufferSizeInBytes = 100 * 1024;
// Can store results for 30 seconds with 1 ms sampling interval.
const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize;
// ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
@@ -645,7 +647,7 @@
// should be made into a common method.
std::string real;
double val = value.as_double;
- if (IsFinite(val)) {
+ if (std::isfinite(val)) {
real = DoubleToString(val);
// Ensure that the number has a .0 if there's no decimal or 'e'. This
// makes sure that when we read the JSON back, it's interpreted as a
@@ -663,7 +665,7 @@
// "-.1" bad "-0.1" good
real.insert(1, "0");
}
- } else if (IsNaN(val)){
+ } else if (std::isnan(val)){
// The JSON spec doesn't allow NaN and Infinity (since these are
// objects in EcmaScript). Use strings instead.
real = "\"NaN\"";
@@ -1208,7 +1210,8 @@
event_callback_category_filter_(
CategoryFilter::kDefaultCategoryFilterString),
thread_shared_chunk_index_(0),
- generation_(0) {
+ generation_(0),
+ use_worker_thread_(false) {
// Trace is enabled or disabled on one thread while other threads are
// accessing the enabled flag. We don't care whether edge-case events are
// traced or not, so we allow races on the enabled flag to keep the trace
@@ -1290,6 +1293,11 @@
if (event_callback_ &&
event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
+#if defined(OS_WIN)
+ if (base::trace_event::TraceEventETWExport::isETWExportEnabled())
+ enabled_flag |= ENABLED_FOR_ETW_EXPORT;
+#endif
+
g_category_group_enabled[category_index] = enabled_flag;
}
@@ -1681,7 +1689,9 @@
// - The message loop will be removed from thread_message_loops_;
// If this is the last message loop, finish the flush;
// 4. If any thread hasn't finish its flush in time, finish the flush.
-void TraceLog::Flush(const TraceLog::OutputCallback& cb) {
+void TraceLog::Flush(const TraceLog::OutputCallback& cb,
+ bool use_worker_thread) {
+ use_worker_thread_ = use_worker_thread;
if (IsEnabled()) {
// Can't flush when tracing is enabled because otherwise PostTask would
// - generate more trace events;
@@ -1735,6 +1745,7 @@
FinishFlush(generation);
}
+// Usually it runs on a different thread.
void TraceLog::ConvertTraceEventsToTraceFormat(
scoped_ptr<TraceBuffer> logged_events,
const TraceLog::OutputCallback& flush_output_callback) {
@@ -1749,19 +1760,17 @@
scoped_refptr<RefCountedString> json_events_str_ptr =
new RefCountedString();
- for (size_t i = 0; i < kTraceEventBatchChunks; ++i) {
+ while (json_events_str_ptr->size() < kTraceEventBufferSizeInBytes) {
const TraceBufferChunk* chunk = logged_events->NextChunk();
- if (!chunk) {
- has_more_events = false;
+ has_more_events = chunk != NULL;
+ if (!chunk)
break;
- }
for (size_t j = 0; j < chunk->size(); ++j) {
- if (i > 0 || j > 0)
+ if (json_events_str_ptr->size())
json_events_str_ptr->data().append(",\n");
chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()));
}
}
-
flush_output_callback.Run(json_events_str_ptr, has_more_events);
} while (has_more_events);
}
@@ -1785,6 +1794,16 @@
flush_output_callback_.Reset();
}
+ if (use_worker_thread_ &&
+ WorkerPool::PostTask(
+ FROM_HERE,
+ Bind(&TraceLog::ConvertTraceEventsToTraceFormat,
+ Passed(&previous_logged_events),
+ flush_output_callback),
+ true)) {
+ return;
+ }
+
ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(),
flush_output_callback);
}
@@ -1908,7 +1927,7 @@
DCHECK(!timestamp.is_null());
if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
- id ^= process_id_hash_;
+ id = MangleEventId(id);
TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
TimeTicks now = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP ?
@@ -1971,6 +1990,15 @@
}
}
+#if defined(OS_WIN)
+ // This is done sooner rather than later, to avoid creating the event and
+ // acquiring the lock, which is not needed for ETW as it's already threadsafe.
+ if (*category_group_enabled & ENABLED_FOR_ETW_EXPORT)
+ TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values,
+ convertable_values);
+#endif // OS_WIN
+
std::string console_message;
if (*category_group_enabled &
(ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) {
@@ -2177,6 +2205,10 @@
watch_event_callback_.Reset();
}
+uint64 TraceLog::MangleEventId(uint64 id) {
+ return id ^ process_id_hash_;
+}
+
void TraceLog::AddMetadataEventsWhileLocked() {
lock_.AssertAcquired();
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index efa20c4..33a85c9 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -26,6 +26,7 @@
// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
+// TODO(georgesak): Update/replace these with new ETW macros.
#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
base::trace_event::TraceLog::AddTraceEventEtw( \
TRACE_EVENT_PHASE_BEGIN, \
@@ -446,6 +447,8 @@
ENABLED_FOR_MONITORING = 1 << 1,
// Category group enabled by SetEventCallbackEnabled().
ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
+ // Category group enabled to export events to ETW.
+ ENABLED_FOR_ETW_EXPORT = 1 << 3
};
static TraceLog* GetInstance();
@@ -538,10 +541,11 @@
// Due to the implementation of thread-local buffers, flush can't be
// done when tracing is enabled. If called when tracing is enabled, the
// callback will be called directly with (empty_string, false) to indicate
- // the end of this unsuccessful flush.
+ // the end of this unsuccessful flush. Flush does the serialization
+ // on the same thread if the caller doesn't set use_worker_thread explicitly.
typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&,
bool has_more_events)> OutputCallback;
- void Flush(const OutputCallback& cb);
+ void Flush(const OutputCallback& cb, bool use_worker_thread = false);
void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback);
// Called by TRACE_EVENT* macros, don't call this directly.
@@ -602,6 +606,8 @@
int process_id() const { return process_id_; }
+ uint64 MangleEventId(uint64 id);
+
// Exposed for unittesting:
void WaitSamplingEventForTesting();
@@ -710,7 +716,9 @@
// |generation| is used in the following callbacks to check if the callback
// is called for the flush of the current |logged_events_|.
void FlushCurrentThread(int generation);
- void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events,
+ // Usually it runs on a different thread.
+ static void ConvertTraceEventsToTraceFormat(
+ scoped_ptr<TraceBuffer> logged_events,
const TraceLog::OutputCallback& flush_output_callback);
void FinishFlush(int generation);
void OnFlushTimeout(int generation);
@@ -803,6 +811,7 @@
OutputCallback flush_output_callback_;
scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_;
subtle::AtomicWord generation_;
+ bool use_worker_thread_;
DISALLOW_COPY_AND_ASSIGN(TraceLog);
};
diff --git a/base/trace_event/trace_event_win_unittest.cc b/base/trace_event/trace_event_win_unittest.cc
index 7f1004e..d4dc854 100644
--- a/base/trace_event/trace_event_win_unittest.cc
+++ b/base/trace_event/trace_event_win_unittest.cc
@@ -92,7 +92,7 @@
TraceEventWinTest() {
}
- void SetUp() {
+ void SetUp() override {
bool is_xp = win::GetVersion() < base::win::VERSION_VISTA;
if (is_xp) {
@@ -151,7 +151,7 @@
EXPECT_TRUE(tracelog->IsTracing());
}
- void TearDown() {
+ void TearDown() override {
EtwTraceProperties prop;
if (controller_.session() != 0)
EXPECT_HRESULT_SUCCEEDED(controller_.Stop(&prop));
diff --git a/base/trace_event/winheap_dump_provider_win.cc b/base/trace_event/winheap_dump_provider_win.cc
new file mode 100644
index 0000000..3a4fd87
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win.cc
@@ -0,0 +1,103 @@
+// 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/trace_event/winheap_dump_provider_win.h"
+
+#include <windows.h>
+
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "winheap";
+
+// Report a heap dump to a process memory dump. The |heap_info| structure
+// contains the information about this heap, and |heap_name| will be used to
+// represent it in the report.
+bool ReportHeapDump(ProcessMemoryDump* pmd,
+ const WinHeapInfo& heap_info,
+ const std::string& heap_name) {
+ MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(kDumperFriendlyName, heap_name);
+ if (!dump)
+ return false;
+ dump->set_physical_size_in_bytes(heap_info.committed_size);
+ dump->set_allocated_objects_count(heap_info.block_count);
+ dump->set_allocated_objects_size_in_bytes(heap_info.allocated_size);
+ return true;
+}
+
+} // namespace
+
+WinHeapDumpProvider* WinHeapDumpProvider::GetInstance() {
+ return Singleton<WinHeapDumpProvider,
+ LeakySingletonTraits<WinHeapDumpProvider>>::get();
+}
+
+bool WinHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+ // Retrieves the number of heaps in the current process.
+ DWORD number_of_heaps = ::GetProcessHeaps(0, NULL);
+ WinHeapInfo all_heap_info = {0};
+
+ // Try to retrieve a handle to all the heaps owned by this process. Returns
+ // false if the number of heaps has changed.
+ //
+ // This is inherently racy as is, but it's not something that we observe a lot
+ // in Chrome, the heaps tend to be created at startup only.
+ scoped_ptr<HANDLE[]> all_heaps(new HANDLE[number_of_heaps]);
+ if (::GetProcessHeaps(number_of_heaps, all_heaps.get()) != number_of_heaps)
+ return false;
+
+ // Skip the pointer to the heap array to avoid accounting the memory used by
+ // this dump provider.
+ std::set<void*> block_to_skip;
+ block_to_skip.insert(all_heaps.get());
+
+ // Retrieves some metrics about each heap.
+ for (size_t i = 0; i < number_of_heaps; ++i) {
+ WinHeapInfo heap_info = {0};
+ heap_info.heap_id = all_heaps[i];
+ GetHeapInformation(&heap_info, block_to_skip);
+
+ all_heap_info.allocated_size += heap_info.allocated_size;
+ all_heap_info.committed_size += heap_info.committed_size;
+ all_heap_info.block_count += heap_info.block_count;
+ }
+ // Report the heap dump.
+ if (!ReportHeapDump(pmd, all_heap_info, MemoryAllocatorDump::kRootHeap))
+ return false;
+
+ return true;
+}
+
+const char* WinHeapDumpProvider::GetFriendlyName() const {
+ return kDumperFriendlyName;
+}
+
+bool WinHeapDumpProvider::GetHeapInformation(
+ WinHeapInfo* heap_info,
+ const std::set<void*>& block_to_skip) {
+ CHECK(::HeapLock(heap_info->heap_id) == TRUE);
+ PROCESS_HEAP_ENTRY heap_entry;
+ heap_entry.lpData = nullptr;
+ // Walk over all the entries in this heap.
+ while (::HeapWalk(heap_info->heap_id, &heap_entry) != FALSE) {
+ if (block_to_skip.count(heap_entry.lpData) == 1)
+ continue;
+ if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
+ heap_info->allocated_size += heap_entry.cbData;
+ heap_info->block_count++;
+ } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) {
+ heap_info->committed_size += heap_entry.Region.dwCommittedSize;
+ }
+ }
+ CHECK(::HeapUnlock(heap_info->heap_id) == TRUE);
+ return true;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/winheap_dump_provider_win.h b/base/trace_event/winheap_dump_provider_win.h
new file mode 100644
index 0000000..8abac47
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win.h
@@ -0,0 +1,53 @@
+// 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 BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
+#define BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
+
+#include <set>
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// A structure containing some information about a given heap.
+struct WinHeapInfo {
+ HANDLE heap_id;
+ size_t committed_size;
+ size_t allocated_size;
+ size_t block_count;
+};
+
+// Dump provider which collects process-wide heap memory stats. This provider
+// iterates over all the heaps of the current process to gather some metrics
+// about them.
+class BASE_EXPORT WinHeapDumpProvider : public MemoryDumpProvider {
+ public:
+ static WinHeapDumpProvider* GetInstance();
+
+ // MemoryDumpProvider implementation.
+ bool DumpInto(ProcessMemoryDump* pmd) override;
+ const char* GetFriendlyName() const override;
+
+ private:
+ friend struct DefaultSingletonTraits<WinHeapDumpProvider>;
+
+ // Retrieves the information about given heap. The |heap_info| should contain
+ // a valid handle to an existing heap. The blocks contained in the
+ // |block_to_skip| set will be ignored.
+ bool GetHeapInformation(WinHeapInfo* heap_info,
+ const std::set<void*>& block_to_skip);
+
+ WinHeapDumpProvider() {}
+ ~WinHeapDumpProvider() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(WinHeapDumpProvider);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
diff --git a/base/trace_event/winheap_dump_provider_win_unittest.cc b/base/trace_event/winheap_dump_provider_win_unittest.cc
new file mode 100644
index 0000000..99da18a
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win_unittest.cc
@@ -0,0 +1,27 @@
+// 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/trace_event/winheap_dump_provider_win.h"
+
+#include <windows.h>
+
+#include "base/trace_event/memory_dump_session_state.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace trace_event {
+
+TEST(WinHeapDumpProviderTest, DumpInto) {
+ ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+
+ WinHeapDumpProvider* winheap_dump_provider =
+ WinHeapDumpProvider::GetInstance();
+ ASSERT_NE(static_cast<WinHeapDumpProvider*>(nullptr), winheap_dump_provider);
+
+ ASSERT_TRUE(winheap_dump_provider->DumpInto(&pmd));
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index 5359d89..a60e260 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -28,9 +28,6 @@
namespace tracked_objects {
namespace {
-// Flag to compile out almost all of the task tracking code.
-const bool kTrackAllTaskObjects = true;
-
// TODO(jar): Evaluate the perf impact of enabling this. If the perf impact is
// negligible, enable by default.
// Flag to compile out parent-child link recording.
@@ -366,8 +363,6 @@
DCHECK(thread_data); // TLS should *never* call us with a NULL.
// We must NOT do any allocations during this callback. There is a chance
// that the allocator is no longer active on this thread.
- if (!kTrackAllTaskObjects)
- return; // Not compiled in.
reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup();
}
@@ -390,23 +385,9 @@
}
// static
-void ThreadData::Snapshot(ProcessDataSnapshot* process_data) {
- // Add births that have run to completion to |collected_data|.
- // |birth_counts| tracks the total number of births recorded at each location
- // for which we have not seen a death count.
- BirthCountMap birth_counts;
- ThreadData::SnapshotAllExecutedTasks(process_data, &birth_counts);
-
- // Add births that are still active -- i.e. objects that have tallied a birth,
- // but have not yet tallied a matching death, and hence must be either
- // running, queued up, or being held in limbo for future posting.
- for (BirthCountMap::const_iterator it = birth_counts.begin();
- it != birth_counts.end(); ++it) {
- if (it->second > 0) {
- process_data->tasks.push_back(
- TaskSnapshot(*it->first, DeathData(it->second), "Still_Alive"));
- }
- }
+void ThreadData::Snapshot(ProcessDataSnapshot* process_data_snapshot) {
+ ThreadData::SnapshotCurrentPhase(
+ &process_data_snapshot->phased_process_data_snapshots[0]);
}
Births* ThreadData::TallyABirth(const Location& location) {
@@ -479,9 +460,6 @@
// static
Births* ThreadData::TallyABirthIfActive(const Location& location) {
- if (!kTrackAllTaskObjects)
- return NULL; // Not compiled in.
-
if (!TrackingStatus())
return NULL;
ThreadData* current_thread_data = Get();
@@ -494,9 +472,6 @@
void ThreadData::TallyRunOnNamedThreadIfTracking(
const base::TrackingInfo& completed_task,
const TaskStopwatch& stopwatch) {
- if (!kTrackAllTaskObjects)
- return; // Not compiled in.
-
// Even if we have been DEACTIVATED, we will process any pending births so
// that our data structures (which counted the outstanding births) remain
// consistent.
@@ -526,9 +501,6 @@
const Births* birth,
const TrackedTime& time_posted,
const TaskStopwatch& stopwatch) {
- if (!kTrackAllTaskObjects)
- return; // Not compiled in.
-
// Even if we have been DEACTIVATED, we will process any pending births so
// that our data structures (which counted the outstanding births) remain
// consistent.
@@ -560,9 +532,6 @@
void ThreadData::TallyRunInAScopedRegionIfTracking(
const Births* birth,
const TaskStopwatch& stopwatch) {
- if (!kTrackAllTaskObjects)
- return; // Not compiled in.
-
// Even if we have been DEACTIVATED, we will process any pending births so
// that our data structures (which counted the outstanding births) remain
// consistent.
@@ -578,11 +547,9 @@
}
// static
-void ThreadData::SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
- BirthCountMap* birth_counts) {
- if (!kTrackAllTaskObjects)
- return; // Not compiled in.
-
+void ThreadData::SnapshotAllExecutedTasks(
+ ProcessDataPhaseSnapshot* process_data_phase,
+ BirthCountMap* birth_counts) {
// Get an unchanging copy of a ThreadData list.
ThreadData* my_list = ThreadData::first();
@@ -595,12 +562,33 @@
for (ThreadData* thread_data = my_list;
thread_data;
thread_data = thread_data->next()) {
- thread_data->SnapshotExecutedTasks(process_data, birth_counts);
+ thread_data->SnapshotExecutedTasks(process_data_phase, birth_counts);
}
}
-void ThreadData::SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
- BirthCountMap* birth_counts) {
+// static
+void ThreadData::SnapshotCurrentPhase(
+ ProcessDataPhaseSnapshot* process_data_phase) {
+ // Add births that have run to completion to |collected_data|.
+ // |birth_counts| tracks the total number of births recorded at each location
+ // for which we have not seen a death count.
+ BirthCountMap birth_counts;
+ ThreadData::SnapshotAllExecutedTasks(process_data_phase, &birth_counts);
+
+ // Add births that are still active -- i.e. objects that have tallied a birth,
+ // but have not yet tallied a matching death, and hence must be either
+ // running, queued up, or being held in limbo for future posting.
+ for (const auto& birth_count : birth_counts) {
+ if (birth_count.second > 0) {
+ process_data_phase->tasks.push_back(TaskSnapshot(
+ *birth_count.first, DeathData(birth_count.second), "Still_Alive"));
+ }
+ }
+}
+
+void ThreadData::SnapshotExecutedTasks(
+ ProcessDataPhaseSnapshot* process_data_phase,
+ BirthCountMap* birth_counts) {
// Get copy of data, so that the data will not change during the iterations
// and processing.
ThreadData::BirthMap birth_map;
@@ -608,24 +596,22 @@
ThreadData::ParentChildSet parent_child_set;
SnapshotMaps(&birth_map, &death_map, &parent_child_set);
- for (ThreadData::DeathMap::const_iterator it = death_map.begin();
- it != death_map.end(); ++it) {
- process_data->tasks.push_back(
- TaskSnapshot(*it->first, it->second, thread_name()));
- (*birth_counts)[it->first] -= it->first->birth_count();
+ for (const auto& death : death_map) {
+ process_data_phase->tasks.push_back(
+ TaskSnapshot(*death.first, death.second, thread_name()));
+ (*birth_counts)[death.first] -= death.first->birth_count();
}
- for (ThreadData::BirthMap::const_iterator it = birth_map.begin();
- it != birth_map.end(); ++it) {
- (*birth_counts)[it->second] += it->second->birth_count();
+ for (const auto& birth : birth_map) {
+ (*birth_counts)[birth.second] += birth.second->birth_count();
}
if (!kTrackParentChildLinks)
return;
- for (ThreadData::ParentChildSet::const_iterator it = parent_child_set.begin();
- it != parent_child_set.end(); ++it) {
- process_data->descendants.push_back(ParentChildPairSnapshot(*it));
+ for (const auto& parent_child : parent_child_set) {
+ process_data_phase->descendants.push_back(
+ ParentChildPairSnapshot(parent_child));
}
}
@@ -634,20 +620,16 @@
DeathMap* death_map,
ParentChildSet* parent_child_set) {
base::AutoLock lock(map_lock_);
- for (BirthMap::const_iterator it = birth_map_.begin();
- it != birth_map_.end(); ++it)
- (*birth_map)[it->first] = it->second;
- for (DeathMap::iterator it = death_map_.begin();
- it != death_map_.end(); ++it) {
- (*death_map)[it->first] = it->second;
- }
+ for (const auto& birth : birth_map_)
+ (*birth_map)[birth.first] = birth.second;
+ for (const auto& death : death_map_)
+ (*death_map)[death.first] = death.second;
if (!kTrackParentChildLinks)
return;
- for (ParentChildSet::iterator it = parent_child_set_.begin();
- it != parent_child_set_.end(); ++it)
- parent_child_set->insert(*it);
+ for (const auto& parent_child : parent_child_set_)
+ parent_child_set->insert(parent_child);
}
static void OptionallyInitializeAlternateTimer() {
@@ -657,8 +639,6 @@
}
bool ThreadData::Initialize() {
- if (!kTrackAllTaskObjects)
- return false; // Not compiled in.
if (status_ >= DEACTIVATED)
return true; // Someone else did the initialization.
// Due to racy lazy initialization in tests, we'll need to recheck status_
@@ -759,7 +739,7 @@
TrackedTime ThreadData::Now() {
if (kAllowAlternateTimeSourceHandling && now_function_)
return TrackedTime::FromMilliseconds((*now_function_)());
- if (kTrackAllTaskObjects && IsProfilerTimingEnabled() && TrackingStatus())
+ if (IsProfilerTimingEnabled() && TrackingStatus())
return TrackedTime::Now();
return TrackedTime(); // Super fast when disabled, or not compiled.
}
@@ -959,13 +939,22 @@
}
//------------------------------------------------------------------------------
-// ProcessDataSnapshot
+// ProcessDataPhaseSnapshot
+
+ProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot() {
+}
+
+ProcessDataPhaseSnapshot::~ProcessDataPhaseSnapshot() {
+}
+
+//------------------------------------------------------------------------------
+// ProcessDataPhaseSnapshot
ProcessDataSnapshot::ProcessDataSnapshot()
#if !defined(OS_NACL)
: process_id(base::GetCurrentProcId()) {
#else
- : process_id(0) {
+ : process_id(base::kNullProcessId) {
#endif
}
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 34c3667..9643265 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -18,6 +18,7 @@
#include "base/gtest_prod_util.h"
#include "base/lazy_instance.h"
#include "base/location.h"
+#include "base/process/process_handle.h"
#include "base/profiler/alternate_timer.h"
#include "base/profiler/tracked_time.h"
#include "base/synchronization/lock.h"
@@ -147,10 +148,14 @@
// TaskSnapshot instances, so that such instances can be sorted and
// aggregated (and remain frozen during our processing).
//
-// The ProcessDataSnapshot struct is a serialized representation of the list
-// of ThreadData objects for a process. It holds a set of TaskSnapshots
-// and tracks parent/child relationships for the executed tasks. The statistics
-// in a snapshot are gathered asynhcronously relative to their ongoing updates.
+// Profiling consists of phases. The concrete phase in the sequence of phases is
+// identified by its 0-based index.
+//
+// The ProcessDataPhaseSnapshot struct is a serialized representation of the
+// list of ThreadData objects for a process for a concrete profiling phase. It
+// holds a set of TaskSnapshots and tracks parent/child relationships for the
+// executed tasks. The statistics in a snapshot are gathered asynhcronously
+// relative to their ongoing updates.
// It is possible, though highly unlikely, that stats could be incorrectly
// recorded by this process (all data is held in 32 bit ints, but we are not
// atomically collecting all data, so we could have count that does not, for
@@ -342,9 +347,15 @@
// We also have a linked list of ThreadData instances, and that list is used to
// harvest data from all existing instances.
+struct ProcessDataPhaseSnapshot;
struct ProcessDataSnapshot;
class BASE_EXPORT TaskStopwatch;
+// Map from profiling phase number to the process-wide snapshotted
+// representation of the list of ThreadData objects that died during the given
+// phase.
+typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap;
+
class BASE_EXPORT ThreadData {
public:
// Current allowable states of the tracking system. The states can vary
@@ -376,8 +387,9 @@
// This may return NULL if the system is disabled for any reason.
static ThreadData* Get();
- // Fills |process_data| with all the recursive results in our process.
- static void Snapshot(ProcessDataSnapshot* process_data);
+ // Fills |process_data_snapshot| with phased snapshots of all profiling
+ // phases, including the current one.
+ static void Snapshot(ProcessDataSnapshot* process_data_snapshot);
// Finds (or creates) a place to count births from the given location in this
// thread, and increment that tally.
@@ -403,16 +415,14 @@
// the task.
// The |end_of_run| was just obtained by a call to Now() (just after the task
// finished).
- static void TallyRunOnWorkerThreadIfTracking(
- const Births* birth,
- const TrackedTime& time_posted,
- const TaskStopwatch& stopwatch);
+ static void TallyRunOnWorkerThreadIfTracking(const Births* birth,
+ const TrackedTime& time_posted,
+ const TaskStopwatch& stopwatch);
// Record the end of execution in region, generally corresponding to a scope
// being exited.
- static void TallyRunInAScopedRegionIfTracking(
- const Births* birth,
- const TaskStopwatch& stopwatch);
+ static void TallyRunInAScopedRegionIfTracking(const Births* birth,
+ const TaskStopwatch& stopwatch);
const std::string& thread_name() const { return thread_name_; }
@@ -514,16 +524,21 @@
// Snapshot (under a lock) the profiled data for the tasks in each ThreadData
// instance. Also updates the |birth_counts| tally for each task to keep
// track of the number of living instances of the task.
- static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
- BirthCountMap* birth_counts);
+ static void SnapshotAllExecutedTasks(
+ ProcessDataPhaseSnapshot* process_data_phase,
+ BirthCountMap* birth_counts);
+
+ // Fills |process_data_phase| with all the recursive results in our process.
+ static void SnapshotCurrentPhase(
+ ProcessDataPhaseSnapshot* process_data_phase);
// Snapshots (under a lock) the profiled data for the tasks for this thread
// and writes all of the executed tasks' data -- i.e. the data for the tasks
- // with with entries in the death_map_ -- into |process_data|. Also updates
- // the |birth_counts| tally for each task to keep track of the number of
- // living instances of the task -- that is, each task maps to the number of
+ // with with entries in the death_map_ -- into |process_data_phase|. Also
+ // updates the |birth_counts| tally for each task to keep track of the number
+ // of living instances of the task -- that is, each task maps to the number of
// births for the task that have not yet been balanced by a death.
- void SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
+ void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase,
BirthCountMap* birth_counts);
// Using our lock, make a copy of the specified maps. This call may be made
@@ -747,16 +762,29 @@
};
//------------------------------------------------------------------------------
-// A snapshotted representation of the list of ThreadData objects for a process.
+// A snapshotted representation of the list of ThreadData objects for a process,
+// for a single profiling phase.
+
+struct BASE_EXPORT ProcessDataPhaseSnapshot {
+ public:
+ ProcessDataPhaseSnapshot();
+ ~ProcessDataPhaseSnapshot();
+
+ std::vector<TaskSnapshot> tasks;
+ std::vector<ParentChildPairSnapshot> descendants;
+};
+
+//------------------------------------------------------------------------------
+// A snapshotted representation of the list of ThreadData objects for a process,
+// for all profiling phases, including the current one.
struct BASE_EXPORT ProcessDataSnapshot {
public:
ProcessDataSnapshot();
~ProcessDataSnapshot();
- std::vector<TaskSnapshot> tasks;
- std::vector<ParentChildPairSnapshot> descendants;
- int process_id;
+ PhasedProcessDataSnapshotMap phased_process_data_snapshots;
+ base::ProcessId process_id;
};
} // namespace tracked_objects
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc
index 7713091..5455fef 100644
--- a/base/tracked_objects_unittest.cc
+++ b/base/tracked_objects_unittest.cc
@@ -71,28 +71,37 @@
int count,
int run_ms,
int queue_ms) {
- ASSERT_EQ(1u, process_data.tasks.size());
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
- EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
+ ASSERT_EQ(1u, process_data_phase.tasks.size());
+
+ EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
EXPECT_EQ(function_name,
- process_data.tasks[0].birth.location.function_name);
- EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
+ process_data_phase.tasks[0].birth.location.function_name);
+ EXPECT_EQ(kLineNumber,
+ process_data_phase.tasks[0].birth.location.line_number);
- EXPECT_EQ(birth_thread, process_data.tasks[0].birth.thread_name);
+ EXPECT_EQ(birth_thread, process_data_phase.tasks[0].birth.thread_name);
- EXPECT_EQ(count, process_data.tasks[0].death_data.count);
+ EXPECT_EQ(count, process_data_phase.tasks[0].death_data.count);
EXPECT_EQ(count * run_ms,
- process_data.tasks[0].death_data.run_duration_sum);
- EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_max);
- EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_sample);
+ process_data_phase.tasks[0].death_data.run_duration_sum);
+ EXPECT_EQ(run_ms, process_data_phase.tasks[0].death_data.run_duration_max);
+ EXPECT_EQ(run_ms,
+ process_data_phase.tasks[0].death_data.run_duration_sample);
EXPECT_EQ(count * queue_ms,
- process_data.tasks[0].death_data.queue_duration_sum);
- EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_max);
- EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_sample);
+ process_data_phase.tasks[0].death_data.queue_duration_sum);
+ EXPECT_EQ(queue_ms,
+ process_data_phase.tasks[0].death_data.queue_duration_max);
+ EXPECT_EQ(queue_ms,
+ process_data_phase.tasks[0].death_data.queue_duration_sample);
- EXPECT_EQ(death_thread, process_data.tasks[0].death_thread_name);
+ EXPECT_EQ(death_thread, process_data_phase.tasks[0].death_thread_name);
- EXPECT_EQ(0u, process_data.descendants.size());
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
@@ -230,37 +239,49 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
- ASSERT_EQ(1u, process_data.tasks.size());
- EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
- EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name);
- EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
- EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].birth.thread_name);
- EXPECT_EQ(1, process_data.tasks[0].death_data.count);
- EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sum);
- EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_max);
- EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sample);
- EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sum);
- EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_max);
- EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sample);
- EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].death_thread_name);
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+ ASSERT_EQ(1u, process_data_phase.tasks.size());
+ EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
+ EXPECT_EQ(kFunction,
+ process_data_phase.tasks[0].birth.location.function_name);
+ EXPECT_EQ(kLineNumber,
+ process_data_phase.tasks[0].birth.location.line_number);
+ EXPECT_EQ(kWorkerThreadName, process_data_phase.tasks[0].birth.thread_name);
+ EXPECT_EQ(1, process_data_phase.tasks[0].death_data.count);
+ EXPECT_EQ(time_elapsed,
+ process_data_phase.tasks[0].death_data.run_duration_sum);
+ EXPECT_EQ(time_elapsed,
+ process_data_phase.tasks[0].death_data.run_duration_max);
+ EXPECT_EQ(time_elapsed,
+ process_data_phase.tasks[0].death_data.run_duration_sample);
+ EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_sum);
+ EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_max);
+ EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_sample);
+ EXPECT_EQ(kWorkerThreadName, process_data_phase.tasks[0].death_thread_name);
if (ThreadData::TrackingParentChildStatus()) {
- ASSERT_EQ(1u, process_data.descendants.size());
- EXPECT_EQ(kFile, process_data.descendants[0].parent.location.file_name);
+ ASSERT_EQ(1u, process_data_phase.descendants.size());
+ EXPECT_EQ(kFile,
+ process_data_phase.descendants[0].parent.location.file_name);
EXPECT_EQ(kFunction,
- process_data.descendants[0].parent.location.function_name);
+ process_data_phase.descendants[0].parent.location.function_name);
EXPECT_EQ(kLineNumber,
- process_data.descendants[0].parent.location.line_number);
+ process_data_phase.descendants[0].parent.location.line_number);
EXPECT_EQ(kWorkerThreadName,
- process_data.descendants[0].parent.thread_name);
- EXPECT_EQ(kFile, process_data.descendants[0].child.location.file_name);
+ process_data_phase.descendants[0].parent.thread_name);
+ EXPECT_EQ(kFile,
+ process_data_phase.descendants[0].child.location.file_name);
EXPECT_EQ(kFunction,
- process_data.descendants[0].child.location.function_name);
+ process_data_phase.descendants[0].child.location.function_name);
EXPECT_EQ(kLineNumber,
- process_data.descendants[0].child.location.line_number);
- EXPECT_EQ(kWorkerThreadName, process_data.descendants[0].child.thread_name);
+ process_data_phase.descendants[0].child.location.line_number);
+ EXPECT_EQ(kWorkerThreadName,
+ process_data_phase.descendants[0].child.thread_name);
} else {
- EXPECT_EQ(0u, process_data.descendants.size());
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
}
}
@@ -318,8 +339,14 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
- EXPECT_EQ(0u, process_data.tasks.size());
- EXPECT_EQ(0u, process_data.descendants.size());
+
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+ EXPECT_EQ(0u, process_data_phase.tasks.size());
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
@@ -335,8 +362,14 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
- EXPECT_EQ(0u, process_data.tasks.size());
- EXPECT_EQ(0u, process_data.descendants.size());
+
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+ EXPECT_EQ(0u, process_data_phase.tasks.size());
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
@@ -425,8 +458,8 @@
pending_task.time_posted = kTimePosted; // Overwrite implied Now().
// Turn off tracking now that we have births.
- EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus(
- ThreadData::DEACTIVATED));
+ EXPECT_TRUE(
+ ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED));
const unsigned int kStartOfRun = 5;
const unsigned int kEndOfRun = 7;
@@ -474,8 +507,14 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
- EXPECT_EQ(0u, process_data.tasks.size());
- EXPECT_EQ(0u, process_data.descendants.size());
+
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+ EXPECT_EQ(0u, process_data_phase.tasks.size());
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
@@ -558,34 +597,43 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
- ASSERT_EQ(2u, process_data.tasks.size());
- EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
- EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name);
- EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
- EXPECT_EQ(kMainThreadName, process_data.tasks[0].birth.thread_name);
- EXPECT_EQ(1, process_data.tasks[0].death_data.count);
- EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sum);
- EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_max);
- EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sample);
- EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sum);
- EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_max);
- EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sample);
- EXPECT_EQ(kMainThreadName, process_data.tasks[0].death_thread_name);
- EXPECT_EQ(kFile, process_data.tasks[1].birth.location.file_name);
- EXPECT_EQ(kFunction, process_data.tasks[1].birth.location.function_name);
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+ ASSERT_EQ(2u, process_data_phase.tasks.size());
+
+ EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
+ EXPECT_EQ(kFunction,
+ process_data_phase.tasks[0].birth.location.function_name);
+ EXPECT_EQ(kLineNumber,
+ process_data_phase.tasks[0].birth.location.line_number);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[0].birth.thread_name);
+ EXPECT_EQ(1, process_data_phase.tasks[0].death_data.count);
+ EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_sum);
+ EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_max);
+ EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_sample);
+ EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_sum);
+ EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_max);
+ EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_sample);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[0].death_thread_name);
+ EXPECT_EQ(kFile, process_data_phase.tasks[1].birth.location.file_name);
+ EXPECT_EQ(kFunction,
+ process_data_phase.tasks[1].birth.location.function_name);
EXPECT_EQ(kSecondFakeLineNumber,
- process_data.tasks[1].birth.location.line_number);
- EXPECT_EQ(kMainThreadName, process_data.tasks[1].birth.thread_name);
- EXPECT_EQ(1, process_data.tasks[1].death_data.count);
- EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sum);
- EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_max);
- EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sample);
- EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sum);
- EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_max);
- EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sample);
- EXPECT_EQ(kStillAlive, process_data.tasks[1].death_thread_name);
- EXPECT_EQ(0u, process_data.descendants.size());
+ process_data_phase.tasks[1].birth.location.line_number);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[1].birth.thread_name);
+ EXPECT_EQ(1, process_data_phase.tasks[1].death_data.count);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_sum);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_max);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_sample);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_sum);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_max);
+ EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_sample);
+ EXPECT_EQ(kStillAlive, process_data_phase.tasks[1].death_thread_name);
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
@@ -719,38 +767,48 @@
ProcessDataSnapshot process_data;
ThreadData::Snapshot(&process_data);
+ ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+ auto it = process_data.phased_process_data_snapshots.find(0);
+ ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+ const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
// The order in which the two task follow is platform-dependent.
- int t0 = (process_data.tasks[0].birth.location.line_number == kLineNumber) ?
- 0 : 1;
+ int t0 =
+ (process_data_phase.tasks[0].birth.location.line_number == kLineNumber)
+ ? 0
+ : 1;
int t1 = 1 - t0;
- ASSERT_EQ(2u, process_data.tasks.size());
- EXPECT_EQ(kFile, process_data.tasks[t0].birth.location.file_name);
- EXPECT_EQ(kFunction, process_data.tasks[t0].birth.location.function_name);
- EXPECT_EQ(kLineNumber, process_data.tasks[t0].birth.location.line_number);
- EXPECT_EQ(kMainThreadName, process_data.tasks[t0].birth.thread_name);
- EXPECT_EQ(1, process_data.tasks[t0].death_data.count);
- EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_sum);
- EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_max);
- EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_sample);
- EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_sum);
- EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_max);
- EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_sample);
- EXPECT_EQ(kMainThreadName, process_data.tasks[t0].death_thread_name);
- EXPECT_EQ(kFile, process_data.tasks[t1].birth.location.file_name);
- EXPECT_EQ(kFunction, process_data.tasks[t1].birth.location.function_name);
+ ASSERT_EQ(2u, process_data_phase.tasks.size());
+ EXPECT_EQ(kFile, process_data_phase.tasks[t0].birth.location.file_name);
+ EXPECT_EQ(kFunction,
+ process_data_phase.tasks[t0].birth.location.function_name);
+ EXPECT_EQ(kLineNumber,
+ process_data_phase.tasks[t0].birth.location.line_number);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t0].birth.thread_name);
+ EXPECT_EQ(1, process_data_phase.tasks[t0].death_data.count);
+ EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_sum);
+ EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_max);
+ EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_sample);
+ EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_sum);
+ EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_max);
+ EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_sample);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t0].death_thread_name);
+ EXPECT_EQ(kFile, process_data_phase.tasks[t1].birth.location.file_name);
+ EXPECT_EQ(kFunction,
+ process_data_phase.tasks[t1].birth.location.function_name);
EXPECT_EQ(kSecondFakeLineNumber,
- process_data.tasks[t1].birth.location.line_number);
- EXPECT_EQ(kMainThreadName, process_data.tasks[t1].birth.thread_name);
- EXPECT_EQ(1, process_data.tasks[t1].death_data.count);
- EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_sum);
- EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_max);
- EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_sample);
- EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_sum);
- EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_max);
- EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_sample);
- EXPECT_EQ(kMainThreadName, process_data.tasks[t1].death_thread_name);
- EXPECT_EQ(0u, process_data.descendants.size());
+ process_data_phase.tasks[t1].birth.location.line_number);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t1].birth.thread_name);
+ EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.count);
+ EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_sum);
+ EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_max);
+ EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_sample);
+ EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_sum);
+ EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_max);
+ EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_sample);
+ EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t1].death_thread_name);
+ EXPECT_EQ(0u, process_data_phase.descendants.size());
EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
}
diff --git a/base/tuple.h b/base/tuple.h
index 41c6a00..88c3075 100644
--- a/base/tuple.h
+++ b/base/tuple.h
@@ -81,6 +81,12 @@
template <> struct MakeIndexSequenceImpl<11> {
using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10>;
};
+template <> struct MakeIndexSequenceImpl<12> {
+ using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11>;
+};
+template <> struct MakeIndexSequenceImpl<13> {
+ using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11,12>;
+};
#else // defined(WIN) && defined(_PREFAST_)
diff --git a/base/values.cc b/base/values.cc
index 52876cf..0e1e2b1 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -7,9 +7,9 @@
#include <string.h>
#include <algorithm>
+#include <cmath>
#include <ostream>
-#include "base/float_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/move.h"
@@ -175,7 +175,7 @@
FundamentalValue::FundamentalValue(double in_value)
: Value(TYPE_DOUBLE), double_value_(in_value) {
- if (!IsFinite(double_value_)) {
+ if (!std::isfinite(double_value_)) {
NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
<< "values cannot be represented in JSON";
double_value_ = 0.0;
diff --git a/base/win/enum_variant.h b/base/win/enum_variant.h
index d978eaa..2caaccd 100644
--- a/base/win/enum_variant.h
+++ b/base/win/enum_variant.h
@@ -39,7 +39,7 @@
STDMETHODIMP Clone(IEnumVARIANT** out_cloned_object) override;
private:
- ~EnumVariant();
+ ~EnumVariant() override;
scoped_ptr<VARIANT[]> items_;
unsigned long count_;
diff --git a/base/win/event_trace_consumer.h b/base/win/event_trace_consumer.h
index 9322e1e..fd44894 100644
--- a/base/win/event_trace_consumer.h
+++ b/base/win/event_trace_consumer.h
@@ -119,7 +119,7 @@
template <class ImplClass> inline
HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
ULONG err = ::ProcessTrace(&trace_handles_[0],
- trace_handles_.size(),
+ static_cast<ULONG>(trace_handles_.size()),
NULL,
NULL);
return HRESULT_FROM_WIN32(err);
diff --git a/base/win/event_trace_consumer_unittest.cc b/base/win/event_trace_consumer_unittest.cc
index 3043152..ecbf238 100644
--- a/base/win/event_trace_consumer_unittest.cc
+++ b/base/win/event_trace_consumer_unittest.cc
@@ -82,7 +82,7 @@
: session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
}
- virtual void SetUp() {
+ void SetUp() override {
// Cleanup any potentially dangling sessions.
EtwTraceProperties ignore;
EtwTraceController::Stop(session_name_.c_str(), &ignore);
@@ -91,7 +91,7 @@
ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
}
- virtual void TearDown() {
+ void TearDown() override {
// Cleanup any potentially dangling sessions.
EtwTraceProperties ignore;
EtwTraceController::Stop(session_name_.c_str(), &ignore);
@@ -125,13 +125,13 @@
class EtwTraceConsumerRealtimeTest: public EtwTraceConsumerBaseTest {
public:
- virtual void SetUp() {
+ void SetUp() override {
EtwTraceConsumerBaseTest::SetUp();
ASSERT_HRESULT_SUCCEEDED(
consumer_.OpenRealtimeSession(session_name_.c_str()));
}
- virtual void TearDown() {
+ void TearDown() override {
consumer_.Close();
EtwTraceConsumerBaseTest::TearDown();
}
@@ -261,7 +261,7 @@
EtwTraceConsumerDataTest() {
}
- virtual void SetUp() {
+ void SetUp() override {
EtwTraceConsumerBaseTest::SetUp();
EtwTraceProperties prop;
@@ -273,7 +273,7 @@
temp_file_ = temp_dir_.path().Append(L"test.etl");
}
- virtual void TearDown() {
+ void TearDown() override {
EXPECT_TRUE(base::DeleteFile(temp_file_, false));
EtwTraceConsumerBaseTest::TearDown();
diff --git a/base/win/event_trace_controller_unittest.cc b/base/win/event_trace_controller_unittest.cc
index be11128..a2cd81c 100644
--- a/base/win/event_trace_controller_unittest.cc
+++ b/base/win/event_trace_controller_unittest.cc
@@ -42,12 +42,8 @@
}
private:
- virtual void OnEventsEnabled() {
- ::SetEvent(callback_event_.Get());
- }
- virtual void PostEventsDisabled() {
- ::SetEvent(callback_event_.Get());
- }
+ void OnEventsEnabled() override { ::SetEvent(callback_event_.Get()); }
+ void PostEventsDisabled() override { ::SetEvent(callback_event_.Get()); }
ScopedHandle callback_event_;
@@ -113,7 +109,7 @@
: session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
}
- virtual void SetUp() {
+ void SetUp() override {
EtwTraceProperties ignore;
EtwTraceController::Stop(session_name_.c_str(), &ignore);
@@ -121,7 +117,7 @@
ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
}
- virtual void TearDown() {
+ void TearDown() override {
EtwTraceProperties prop;
EtwTraceController::Stop(session_name_.c_str(), &prop);
}
diff --git a/base/win/iunknown_impl.h b/base/win/iunknown_impl.h
index 4283d02..b7de205 100644
--- a/base/win/iunknown_impl.h
+++ b/base/win/iunknown_impl.h
@@ -19,11 +19,11 @@
public:
IUnknownImpl();
- virtual ULONG STDMETHODCALLTYPE AddRef() override;
- virtual ULONG STDMETHODCALLTYPE Release() override;
+ ULONG STDMETHODCALLTYPE AddRef() override;
+ ULONG STDMETHODCALLTYPE Release() override;
// Subclasses should extend this to return any interfaces they provide.
- virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
protected:
virtual ~IUnknownImpl();
diff --git a/base/win/iunknown_impl_unittest.cc b/base/win/iunknown_impl_unittest.cc
index db86214..874a43a 100644
--- a/base/win/iunknown_impl_unittest.cc
+++ b/base/win/iunknown_impl_unittest.cc
@@ -15,9 +15,7 @@
TestIUnknownImplSubclass() {
++instance_count;
}
- virtual ~TestIUnknownImplSubclass() {
- --instance_count;
- }
+ ~TestIUnknownImplSubclass() override { --instance_count; }
static int instance_count;
};
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index 0ae2532..d68d935 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -56,7 +56,7 @@
};
ObjectWatcher();
- ~ObjectWatcher();
+ ~ObjectWatcher() override;
// When the object is signaled, the given delegate is notified on the thread
// where StartWatching is called. The ObjectWatcher is not responsible for
@@ -87,7 +87,7 @@
void Signal(Delegate* delegate);
// MessageLoop::DestructionObserver implementation:
- virtual void WillDestroyCurrentMessageLoop();
+ void WillDestroyCurrentMessageLoop() override;
// Internal state.
Closure callback_;
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index 1a5e9e2..b30ca41 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -17,7 +17,7 @@
class QuitDelegate : public ObjectWatcher::Delegate {
public:
- virtual void OnObjectSignaled(HANDLE object) {
+ void OnObjectSignaled(HANDLE object) override {
MessageLoop::current()->QuitWhenIdle();
}
};
@@ -26,9 +26,8 @@
public:
explicit DecrementCountDelegate(int* counter) : counter_(counter) {
}
- virtual void OnObjectSignaled(HANDLE object) {
- --(*counter_);
- }
+ void OnObjectSignaled(HANDLE object) override { --(*counter_); }
+
private:
int* counter_;
};
diff --git a/base/win/pe_image.cc b/base/win/pe_image.cc
index e226b6a..19b381d 100644
--- a/base/win/pe_image.cc
+++ b/base/win/pe_image.cc
@@ -568,14 +568,12 @@
if (NULL == section_header)
return false;
-#pragma warning(push)
-#pragma warning(disable: 4311)
+#pragma warning(suppress : 4302) // pointer truncation
// These casts generate warnings because they are 32 bit specific.
// Don't follow the virtual RVAToAddr, use the one on the base.
DWORD offset_within_section = reinterpret_cast<DWORD>(address) -
reinterpret_cast<DWORD>(PEImage::RVAToAddr(
section_header->VirtualAddress));
-#pragma warning(pop)
*on_disk_offset = section_header->PointerToRawData + offset_within_section;
return true;
diff --git a/base/win/pe_image.h b/base/win/pe_image.h
index 5cef537..343d286 100644
--- a/base/win/pe_image.h
+++ b/base/win/pe_image.h
@@ -238,7 +238,7 @@
public:
explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {}
- virtual PVOID RVAToAddr(DWORD rva) const;
+ PVOID RVAToAddr(DWORD rva) const override;
};
inline bool PEImage::IsOrdinal(LPCSTR name) {
diff --git a/base/win/registry.cc b/base/win/registry.cc
index d0df48a..47afcbf 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -38,7 +38,7 @@
class RegKey::Watcher : public ObjectWatcher::Delegate {
public:
explicit Watcher(RegKey* owner) : owner_(owner) {}
- ~Watcher() {}
+ ~Watcher() override {}
bool StartWatching(HKEY key, const ChangeCallback& callback);
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 6548474..2257663 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -31,7 +31,7 @@
#endif // _WIN64
RegistryTest() {}
- virtual void SetUp() override {
+ void SetUp() override {
// Create a temporary key.
RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
key.DeleteKey(kRootKey);
@@ -42,7 +42,7 @@
foo_software_key_ += L"\\Foo";
}
- virtual void TearDown() override {
+ void TearDown() override {
// Clean up the temporary key.
RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc
index 2803021..33a8aa5 100644
--- a/base/win/scoped_handle.cc
+++ b/base/win/scoped_handle.cc
@@ -12,6 +12,11 @@
#include "base/logging.h"
#include "base/synchronization/lock_impl.h"
+extern "C" {
+__declspec(dllexport) void* GetHandleVerifier();
+typedef void* (*GetHandleVerifierFn)();
+}
+
namespace {
struct HandleHash {
@@ -30,20 +35,9 @@
};
typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
-// g_lock protects g_handle_map and g_closing.
+// g_lock protects the handle map and setting g_active_verifier.
typedef base::internal::LockImpl NativeLock;
base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER;
-bool g_closing = false;
-
-// g_verifier_enabled is not protected by g_lock because that would require
-// using the lock (hence, synchornizing multiple threads) even when the
-// verifier is not in use. Note that this variable is initialized to track all
-// handles, and it should only move to the disabled state, and never back to
-// enabled, because that would crash when seeing handles created while the
-// verifier was disabled. This also implies that it is OK if the value change is
-// not propagated immediately to all CPUs (as would happen with a lock).
-bool g_verifier_enabled = true;
bool CloseHandleWrapper(HANDLE handle) {
if (!::CloseHandle(handle))
@@ -68,81 +62,184 @@
DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
};
+// Implements the actual object that is verifying handles for this process.
+// The active instance is shared across the module boundary but there is no
+// way to delete this object from the wrong side of it (or any side, actually).
+class ActiveVerifier {
+ public:
+ explicit ActiveVerifier(bool enabled)
+ : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
+ }
+
+ // Retrieves the current verifier.
+ static ActiveVerifier* Get();
+
+ // The methods required by HandleTraits. They are virtual because we need to
+ // forward the call execution to another module, instead of letting the
+ // compiler call the version that is linked in the current module.
+ virtual bool CloseHandle(HANDLE handle);
+ virtual void StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+ virtual void StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2);
+ virtual void Disable();
+ virtual void OnHandleBeingClosed(HANDLE handle);
+
+ private:
+ ~ActiveVerifier(); // Not implemented.
+
+ static void InstallVerifier();
+
+ bool enabled_;
+ bool closing_;
+ NativeLock* lock_;
+ HandleMap map_;
+ DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
+};
+ActiveVerifier* g_active_verifier = NULL;
+
+// static
+ActiveVerifier* ActiveVerifier::Get() {
+ if (!g_active_verifier)
+ ActiveVerifier::InstallVerifier();
+
+ return g_active_verifier;
+}
+
+// static
+void ActiveVerifier::InstallVerifier() {
+#if defined(COMPONENT_BUILD)
+ AutoNativeLock lock(g_lock.Get());
+ g_active_verifier = new ActiveVerifier(true);
+#else
+ // If you are reading this, wondering why your process seems deadlocked, take
+ // a look at your DllMain code and remove things that should not be done
+ // there, like doing whatever gave you that nice windows handle you are trying
+ // to store in a ScopedHandle.
+ HMODULE main_module = ::GetModuleHandle(NULL);
+ GetHandleVerifierFn get_handle_verifier =
+ reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
+ main_module, "GetHandleVerifier"));
+
+ if (!get_handle_verifier) {
+ g_active_verifier = new ActiveVerifier(false);
+ return;
+ }
+
+ ActiveVerifier* verifier =
+ reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
+
+ // This lock only protects against races in this module, which is fine.
+ AutoNativeLock lock(g_lock.Get());
+ g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
+
+ // TODO(shrikant): Enable handle verifier after figuring out
+ // AppContainer/DuplicateHandle error.
+ g_active_verifier->Disable();
+#endif
+}
+
+bool ActiveVerifier::CloseHandle(HANDLE handle) {
+ if (!enabled_)
+ return CloseHandleWrapper(handle);
+
+ AutoNativeLock lock(*lock_);
+ closing_ = true;
+ CloseHandleWrapper(handle);
+ closing_ = false;
+
+ return true;
+}
+
+void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ if (!enabled_)
+ return;
+
+ // Grab the thread id before the lock.
+ DWORD thread_id = GetCurrentThreadId();
+
+ AutoNativeLock lock(*lock_);
+
+ Info handle_info = { owner, pc1, pc2, thread_id };
+ std::pair<HANDLE, Info> item(handle, handle_info);
+ std::pair<HandleMap::iterator, bool> result = map_.insert(item);
+ if (!result.second) {
+ Info other = result.first->second;
+ base::debug::Alias(&other);
+ CHECK(false);
+ }
+}
+
+void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
+ const void* pc1, const void* pc2) {
+ if (!enabled_)
+ return;
+
+ AutoNativeLock lock(*lock_);
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end())
+ CHECK(false);
+
+ Info other = i->second;
+ if (other.owner != owner) {
+ base::debug::Alias(&other);
+ CHECK(false);
+ }
+
+ map_.erase(i);
+}
+
+void ActiveVerifier::Disable() {
+ enabled_ = false;
+}
+
+void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
+ AutoNativeLock lock(*lock_);
+ if (closing_)
+ return;
+
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end())
+ return;
+
+ Info other = i->second;
+ base::debug::Alias(&other);
+ CHECK(false);
+}
+
} // namespace
+void* GetHandleVerifier() {
+ return g_active_verifier;
+}
+
namespace base {
namespace win {
// Static.
bool HandleTraits::CloseHandle(HANDLE handle) {
- if (!g_verifier_enabled)
- return CloseHandleWrapper(handle);
-
- AutoNativeLock lock(g_lock.Get());
- g_closing = true;
- CloseHandleWrapper(handle);
- g_closing = false;
-
- return true;
+ return ActiveVerifier::Get()->CloseHandle(handle);
}
// Static.
void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
const void* pc1, const void* pc2) {
- if (!g_verifier_enabled)
- return;
-
- // Grab the thread id before the lock.
- DWORD thread_id = GetCurrentThreadId();
-
- AutoNativeLock lock(g_lock.Get());
-
- Info handle_info = { owner, pc1, pc2, thread_id };
- std::pair<HANDLE, Info> item(handle, handle_info);
- std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item);
- if (!result.second) {
- Info other = result.first->second;
- debug::Alias(&other);
- CHECK(false);
- }
+ return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2);
}
// Static.
void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
const void* pc1, const void* pc2) {
- if (!g_verifier_enabled)
- return;
-
- AutoNativeLock lock(g_lock.Get());
- HandleMap::iterator i = g_handle_map.Get().find(handle);
- if (i == g_handle_map.Get().end())
- CHECK(false);
-
- Info other = i->second;
- if (other.owner != owner) {
- debug::Alias(&other);
- CHECK(false);
- }
-
- g_handle_map.Get().erase(i);
+ return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2);
}
void DisableHandleVerifier() {
- g_verifier_enabled = false;
+ return ActiveVerifier::Get()->Disable();
}
void OnHandleBeingClosed(HANDLE handle) {
- AutoNativeLock lock(g_lock.Get());
- if (g_closing)
- return;
-
- HandleMap::iterator i = g_handle_map.Get().find(handle);
- if (i == g_handle_map.Get().end())
- return;
-
- Info other = i->second;
- debug::Alias(&other);
- CHECK(false);
+ return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
}
} // namespace win
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc
index bb24637..634a538 100644
--- a/base/win/scoped_process_information.cc
+++ b/base/win/scoped_process_information.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
namespace base {
namespace win {
@@ -20,11 +21,49 @@
return true;
HANDLE temp = NULL;
- if (!::DuplicateHandle(::GetCurrentProcess(), source,
- ::GetCurrentProcess(), &temp, 0, FALSE,
- DUPLICATE_SAME_ACCESS)) {
- DPLOG(ERROR) << "Failed to duplicate a handle.";
- return false;
+
+ // TODO(shrikant): Remove following code as soon as we gather some
+ // information regarding AppContainer related DuplicateHandle failures that
+ // only seem to happen on certain machine and only random launches (normally
+ // renderer launches seem to succeed even on those machines.)
+ if (base::win::GetVersion() == base::win::VERSION_WIN8 ||
+ base::win::GetVersion() == base::win::VERSION_WIN8_1) {
+ typedef LONG (WINAPI *NtDuplicateObject)(
+ IN HANDLE SourceProcess,
+ IN HANDLE SourceHandle,
+ IN HANDLE TargetProcess,
+ OUT PHANDLE TargetHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Attributes,
+ IN ULONG Options);
+
+ typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status);
+
+ NtDuplicateObject nt_duplicate_object =
+ reinterpret_cast<NtDuplicateObject>(::GetProcAddress(
+ GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject"));
+ if (nt_duplicate_object != NULL) {
+ LONG status = nt_duplicate_object(::GetCurrentProcess(), source,
+ ::GetCurrentProcess(), &temp,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (status < 0) {
+ DPLOG(ERROR) << "Failed to duplicate a handle.";
+ RtlNtStatusToDosError ntstatus_to_doserror =
+ reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress(
+ GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError"));
+ if (ntstatus_to_doserror != NULL) {
+ ::SetLastError(ntstatus_to_doserror(status));
+ }
+ return false;
+ }
+ }
+ } else {
+ if (!::DuplicateHandle(::GetCurrentProcess(), source,
+ ::GetCurrentProcess(), &temp, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ DPLOG(ERROR) << "Failed to duplicate a handle.";
+ return false;
+ }
}
target->Set(temp);
return true;
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc
index eb26cea..207fdbe 100644
--- a/base/win/shortcut.cc
+++ b/base/win/shortcut.cc
@@ -42,6 +42,13 @@
} // namespace
+ShortcutProperties::ShortcutProperties()
+ : icon_index(-1), dual_mode(false), options(0U) {
+}
+
+ShortcutProperties::~ShortcutProperties() {
+}
+
bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path,
const ShortcutProperties& properties,
ShortcutOperation operation) {
diff --git a/base/win/shortcut.h b/base/win/shortcut.h
index 2feb4c3..6f7d10c 100644
--- a/base/win/shortcut.h
+++ b/base/win/shortcut.h
@@ -7,6 +7,7 @@
#include <windows.h>
+#include "base/base_export.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string16.h"
@@ -29,7 +30,7 @@
// creation/update, others will be ignored.
// Callers are encouraged to use the setters provided which take care of
// setting |options| as desired.
-struct ShortcutProperties {
+struct BASE_EXPORT ShortcutProperties {
enum IndividualProperties {
PROPERTIES_TARGET = 1U << 0,
PROPERTIES_WORKING_DIR = 1U << 1,
@@ -48,7 +49,8 @@
PROPERTIES_ALL = PROPERTIES_BASIC | PROPERTIES_WIN7
};
- ShortcutProperties() : icon_index(-1), dual_mode(false), options(0U) {}
+ ShortcutProperties();
+ ~ShortcutProperties();
void set_target(const FilePath& target_in) {
target = target_in;
diff --git a/base/win/shortcut_unittest.cc b/base/win/shortcut_unittest.cc
index 4bb227a..794be23 100644
--- a/base/win/shortcut_unittest.cc
+++ b/base/win/shortcut_unittest.cc
@@ -25,7 +25,7 @@
class ShortcutTest : public testing::Test {
protected:
- virtual void SetUp() override {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(temp_dir_2_.CreateUniqueTempDir());
diff --git a/build/PRESUBMIT.py b/build/PRESUBMIT.py
index 3c70193..fca962f 100644
--- a/build/PRESUBMIT.py
+++ b/build/PRESUBMIT.py
@@ -2,8 +2,6 @@
# 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(
diff --git a/build/all.gyp b/build/all.gyp
index 2813ca2..255a35c 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -74,12 +74,6 @@
'../content/content_shell_and_tests.gyp:content_shell_apk',
'<@(android_app_targets)',
'android_builder_tests',
- '../android_webview/android_webview.gyp:android_webview_apk',
- '../android_webview/android_webview.gyp:system_webview_apk',
- '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
- '../chrome/chrome.gyp:chrome_shell_apk',
- '../chrome/chrome.gyp:chrome_sync_shell_apk',
- '../remoting/remoting.gyp:remoting_apk',
'../tools/telemetry/telemetry.gyp:*#host',
# TODO(nyquist) This should instead by a target for sync when all of
# the sync-related code for Android has been upstreamed.
@@ -87,6 +81,17 @@
'../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib',
],
'conditions': [
+ ['chromecast==0', {
+ 'dependencies': [
+ '../android_webview/android_webview.gyp:android_webview_apk',
+ '../android_webview/android_webview.gyp:system_webview_apk',
+ '../android_webview/android_webview_shell.gyp:android_webview_shell_apk',
+ '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
+ '../chrome/chrome.gyp:chrome_shell_apk',
+ '../chrome/chrome.gyp:chrome_sync_shell_apk',
+ '../remoting/remoting.gyp:remoting_apk',
+ ],
+ }],
['target_arch == "arm" or target_arch == "arm64"', {
'dependencies': [
# The relocation packer only works on ARM or ARM64.
@@ -101,16 +106,16 @@
'../sync/sync.gyp:*',
],
}],
- ['OS!="ios" and OS!="android"', {
+ ['OS!="ios" and OS!="android" and chromecast==0', {
'dependencies': [
'../third_party/re2/re2.gyp:re2',
'../chrome/chrome.gyp:*',
'../chrome/tools/profile_reset/jtl_compiler.gyp:*',
'../cc/blink/cc_blink_tests.gyp:*',
'../cc/cc_tests.gyp:*',
- '../device/bluetooth/bluetooth.gyp:*',
- '../device/device_tests.gyp:*',
'../device/usb/usb.gyp:*',
+ '../extensions/extensions.gyp:*',
+ '../extensions/extensions_tests.gyp:*',
'../gin/gin.gyp:*',
'../gpu/gpu.gyp:*',
'../gpu/tools/tools.gyp:*',
@@ -150,6 +155,12 @@
'<(libjpeg_gyp_path):*',
],
}],
+ ['OS!="ios"', {
+ 'dependencies': [
+ '../device/bluetooth/bluetooth.gyp:*',
+ '../device/device_tests.gyp:*',
+ ],
+ }],
['use_openssl==0 and (OS=="mac" or OS=="ios" or OS=="win")', {
'dependencies': [
'../third_party/nss/nss.gyp:*',
@@ -170,7 +181,6 @@
['OS=="linux"', {
'dependencies': [
'../courgette/courgette.gyp:*',
- '../dbus/dbus.gyp:*',
'../sandbox/sandbox.gyp:*',
],
'conditions': [
@@ -184,6 +194,11 @@
'../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
],
}],
+ ['use_dbus==1', {
+ 'dependencies': [
+ '../dbus/dbus.gyp:*',
+ ],
+ }],
],
}],
['chromecast==1', {
@@ -263,7 +278,7 @@
'../google_apis/gcm/gcm.gyp:*',
],
}],
- ['chromeos==1 or OS=="linux" or OS=="win" or OS=="mac"', {
+ ['(chromeos==1 or OS=="linux" or OS=="win" or OS=="mac") and chromecast==0', {
'dependencies': [
'../extensions/shell/app_shell.gyp:*',
],
@@ -315,19 +330,11 @@
'dependencies': [
'../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
'../cc/cc_tests.gyp:cc_unittests',
- '../chrome/chrome.gyp:browser_tests',
- '../chrome/chrome.gyp:chromedriver_tests',
- '../chrome/chrome.gyp:chromedriver_unittests',
- '../chrome/chrome.gyp:interactive_ui_tests',
- '../chrome/chrome.gyp:sync_integration_tests',
- '../chrome/chrome.gyp:unit_tests',
'../cloud_print/cloud_print.gyp:cloud_print_unittests',
'../content/content_shell_and_tests.gyp:content_browsertests',
'../content/content_shell_and_tests.gyp:content_shell',
'../content/content_shell_and_tests.gyp:content_unittests',
'../device/device_tests.gyp:device_unittests',
- '../extensions/extensions_tests.gyp:extensions_browsertests',
- '../extensions/extensions_tests.gyp:extensions_unittests',
'../gin/gin.gyp:gin_unittests',
'../google_apis/google_apis.gyp:google_apis_unittests',
'../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
@@ -348,6 +355,18 @@
'../tools/telemetry/telemetry.gyp:*',
],
}],
+ ['OS!="ios" and OS!="android" and chromecast==0', {
+ 'dependencies': [
+ '../chrome/chrome.gyp:browser_tests',
+ '../chrome/chrome.gyp:chromedriver_tests',
+ '../chrome/chrome.gyp:chromedriver_unittests',
+ '../chrome/chrome.gyp:interactive_ui_tests',
+ '../chrome/chrome.gyp:sync_integration_tests',
+ '../chrome/chrome.gyp:unit_tests',
+ '../extensions/extensions_tests.gyp:extensions_browsertests',
+ '../extensions/extensions_tests.gyp:extensions_unittests',
+ ],
+ }],
['OS=="win"', {
'dependencies': [
'../chrome/chrome.gyp:app_installer',
@@ -406,10 +425,14 @@
}],
['OS=="linux"', {
'dependencies': [
- '../dbus/dbus.gyp:dbus_unittests',
'../sandbox/sandbox.gyp:sandbox_linux_unittests',
],
}],
+ ['OS=="linux" and use_dbus==1', {
+ 'dependencies': [
+ '../dbus/dbus.gyp:dbus_unittests',
+ ],
+ }],
['OS=="mac"', {
'dependencies': [
'../ui/app_list/app_list.gyp:app_list_unittests',
@@ -436,6 +459,10 @@
'../ui/app_list/app_list.gyp:app_list_unittests',
'../ui/aura/aura.gyp:aura_unittests',
'../ui/compositor/compositor.gyp:compositor_unittests',
+ ],
+ }],
+ ['use_aura==1 and chromecast==0', {
+ 'dependencies': [
'../ui/keyboard/keyboard.gyp:keyboard_unittests',
'../ui/views/views.gyp:views_unittests',
],
@@ -468,7 +495,7 @@
],
'conditions': [
# TODO(GYP): make gn_migration.gypi work unconditionally.
- ['OS=="linux" and target_arch=="x64" and chromeos==0 and chromecast==0 and disable_nacl==0', {
+ ['OS=="mac" or OS=="win" or (OS=="linux" and target_arch=="x64" and chromecast==0)', {
'includes': [
'gn_migration.gypi',
],
@@ -512,14 +539,14 @@
}],
['OS=="linux"', {
'dependencies': [
- '../breakpad/breakpad.gyp:dump_syms',
+ '../breakpad/breakpad.gyp:dump_syms#host',
],
}],
],
}, # target_name: blink_tests
],
}], # OS!=ios
- ['OS!="ios" and OS!="android"', {
+ ['OS!="ios" and OS!="android" and chromecast==0', {
'targets': [
{
'target_name': 'chromium_builder_nacl_win_integration',
@@ -557,6 +584,7 @@
['OS=="win"', {
'dependencies': [
'../chrome/chrome.gyp:crash_service',
+ '../gpu/gpu.gyp:angle_perftests',
],
}],
['OS=="win" and target_arch=="ia32"', {
@@ -759,7 +787,6 @@
'target_name': 'android_builder_tests',
'type': 'none',
'dependencies': [
- '../android_webview/android_webview.gyp:android_webview_unittests',
'../base/android/jni_generator/jni_generator.gyp:jni_generator_tests',
'../base/base.gyp:base_unittests',
'../breakpad/breakpad.gyp:breakpad_unittests_deps',
@@ -774,10 +801,10 @@
'../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
'../cc/cc_tests.gyp:cc_perftests_apk',
'../cc/cc_tests.gyp:cc_unittests',
- '../chrome/chrome.gyp:unit_tests',
'../components/components_tests.gyp:components_unittests',
'../content/content_shell_and_tests.gyp:content_browsertests',
'../content/content_shell_and_tests.gyp:content_gl_tests',
+ '../content/content_shell_and_tests.gyp:content_junit_tests',
'../content/content_shell_and_tests.gyp:chromium_linker_test_apk',
'../content/content_shell_and_tests.gyp:content_shell_test_apk',
'../content/content_shell_and_tests.gyp:content_unittests',
@@ -803,16 +830,10 @@
'../ui/events/events.gyp:events_unittests',
'../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
# Unit test bundles packaged as an apk.
- '../android_webview/android_webview.gyp:android_webview_test_apk',
- '../android_webview/android_webview.gyp:android_webview_unittests_apk',
'../base/base.gyp:base_unittests_apk',
'../cc/blink/cc_blink_tests.gyp:cc_blink_unittests_apk',
'../cc/cc_tests.gyp:cc_unittests_apk',
- '../chrome/chrome.gyp:chrome_shell_test_apk',
- '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
- '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
- '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
- '../chrome/chrome.gyp:unit_tests_apk',
+ '../components/components_tests.gyp:components_browsertests_apk',
'../components/components_tests.gyp:components_unittests_apk',
'../content/content_shell_and_tests.gyp:content_browsertests_apk',
'../content/content_shell_and_tests.gyp:content_gl_tests_apk',
@@ -835,6 +856,21 @@
'../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk',
],
'conditions': [
+ ['chromecast==0', {
+ 'dependencies': [
+ '../android_webview/android_webview.gyp:android_webview_unittests',
+ '../chrome/chrome.gyp:unit_tests',
+ # Unit test bundles packaged as an apk.
+ '../android_webview/android_webview.gyp:android_webview_test_apk',
+ '../android_webview/android_webview.gyp:android_webview_unittests_apk',
+ '../chrome/chrome.gyp:chrome_junit_tests',
+ '../chrome/chrome.gyp:chrome_shell_test_apk',
+ '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
+ '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
+ '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+ '../chrome/chrome.gyp:unit_tests_apk',
+ ],
+ }],
['enable_webrtc==1 and "<(libpeer_target_type)"=="static_library"', {
'dependencies': [
'../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
@@ -1160,14 +1196,10 @@
['branding=="Chrome"', {
'targets': [
{
- 'target_name': 'chrome_official_builder',
+ 'target_name': 'chrome_official_builder_no_unittests',
'type': 'none',
'dependencies': [
- '../base/base.gyp:base_unittests',
'../chrome/chrome.gyp:app_installer',
- '../chrome/chrome.gyp:app_installer_unittests',
- '../chrome/chrome.gyp:browser_tests',
- '../chrome/chrome.gyp:sync_integration_tests',
'../chrome/chrome.gyp:crash_service',
'../chrome/chrome.gyp:gcapi_dll',
'../chrome/chrome.gyp:pack_policy_templates',
@@ -1175,19 +1207,8 @@
'../cloud_print/cloud_print.gyp:cloud_print',
'../courgette/courgette.gyp:courgette',
'../courgette/courgette.gyp:courgette64',
- '../ipc/ipc.gyp:ipc_tests',
- '../media/media.gyp:media_unittests',
- '../net/net.gyp:net_unittests_run',
- '../printing/printing.gyp:printing_unittests',
'../remoting/remoting.gyp:remoting_webapp',
- '../sql/sql.gyp:sql_unittests',
- '../sync/sync.gyp:sync_unit_tests',
'../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
- '../ui/base/ui_base_tests.gyp:ui_base_unittests',
- '../ui/gfx/gfx_tests.gyp:gfx_unittests',
- '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
- '../ui/views/views.gyp:views_unittests',
- '../url/url.gyp:url_unittests',
],
'conditions': [
['target_arch=="ia32"', {
@@ -1202,6 +1223,27 @@
],
}], # component != "shared_library"
]
+ }, {
+ 'target_name': 'chrome_official_builder',
+ 'type': 'none',
+ 'dependencies': [
+ 'chrome_official_builder_no_unittests',
+ '../base/base.gyp:base_unittests',
+ '../chrome/chrome.gyp:app_installer_unittests',
+ '../chrome/chrome.gyp:browser_tests',
+ '../chrome/chrome.gyp:sync_integration_tests',
+ '../ipc/ipc.gyp:ipc_tests',
+ '../media/media.gyp:media_unittests',
+ '../net/net.gyp:net_unittests_run',
+ '../printing/printing.gyp:printing_unittests',
+ '../sql/sql.gyp:sql_unittests',
+ '../sync/sync.gyp:sync_unit_tests',
+ '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+ '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+ '../ui/views/views.gyp:views_unittests',
+ '../url/url.gyp:url_unittests',
+ ],
},
], # targets
}], # branding=="Chrome"
@@ -1215,10 +1257,6 @@
'dependencies': [
'../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
'../cc/cc_tests.gyp:cc_unittests',
- '../chrome/chrome.gyp:browser_tests',
- '../chrome/chrome.gyp:chrome',
- '../chrome/chrome.gyp:interactive_ui_tests',
- '../chrome/chrome.gyp:unit_tests',
'../components/components_tests.gyp:components_unittests',
'../content/content_shell_and_tests.gyp:content_browsertests',
'../content/content_shell_and_tests.gyp:content_unittests',
@@ -1236,12 +1274,8 @@
'../ui/events/events.gyp:*',
'../ui/gfx/gfx_tests.gyp:gfx_unittests',
'../ui/keyboard/keyboard.gyp:*',
- '../ui/message_center/message_center.gyp:*',
'../ui/snapshot/snapshot.gyp:snapshot_unittests',
'../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
- '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
- '../ui/views/views.gyp:views',
- '../ui/views/views.gyp:views_unittests',
'../ui/wm/wm.gyp:*',
'blink_tests',
],
@@ -1283,6 +1317,18 @@
'../ui/ozone/demo/ozone_demos.gyp:*',
],
}],
+ ['chromecast==0', {
+ 'dependencies': [
+ '../chrome/chrome.gyp:browser_tests',
+ '../chrome/chrome.gyp:chrome',
+ '../chrome/chrome.gyp:interactive_ui_tests',
+ '../chrome/chrome.gyp:unit_tests',
+ '../ui/message_center/message_center.gyp:*',
+ '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+ '../ui/views/views.gyp:views',
+ '../ui/views/views.gyp:views_unittests',
+ ],
+ }],
],
},
], # targets
@@ -1294,14 +1340,20 @@
'type': 'none',
'dependencies': [
'../base/base.gyp:base_unittests_run',
- '../chrome/chrome.gyp:browser_tests_run',
- '../chrome/chrome.gyp:interactive_ui_tests_run',
- '../chrome/chrome.gyp:sync_integration_tests_run',
- '../chrome/chrome.gyp:unit_tests_run',
'../content/content_shell_and_tests.gyp:content_browsertests_run',
'../content/content_shell_and_tests.gyp:content_unittests_run',
'../net/net.gyp:net_unittests_run',
],
+ 'conditions': [
+ ['chromecast==0', {
+ 'dependencies': [
+ '../chrome/chrome.gyp:browser_tests_run',
+ '../chrome/chrome.gyp:interactive_ui_tests_run',
+ '../chrome/chrome.gyp:sync_integration_tests_run',
+ '../chrome/chrome.gyp:unit_tests_run',
+ ],
+ }],
+ ],
}, # target_name: chromium_swarm_tests
],
}],
diff --git a/build/android/AndroidManifest.xml b/build/android/AndroidManifest.xml
index 25e1db0..f27872e 100644
--- a/build/android/AndroidManifest.xml
+++ b/build/android/AndroidManifest.xml
@@ -15,6 +15,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dummy.package">
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
</manifest>
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index d1daaf2..92095be 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -8,25 +8,6 @@
details on the presubmit API built into depot_tools.
"""
-_DELETIONS_ONLY_FILES = (
- 'build/android/findbugs_filter/findbugs_known_bugs.txt',
-)
-
-
-def _CheckDeletionsOnlyFiles(input_api, output_api):
- """Check that a certain listed files only have deletions.
- """
- warnings = []
- for f in input_api.AffectedFiles():
- if f.LocalPath() in _DELETIONS_ONLY_FILES:
- if f.ChangedContents():
- warnings.append(f.LocalPath())
- results = []
- if warnings:
- results.append(output_api.PresubmitPromptWarning(
- 'Following files should only contain deletions.', warnings))
- return results
-
def CommonChecks(input_api, output_api):
output = []
@@ -61,6 +42,7 @@
input_api,
output_api,
unit_tests=[
+ J('pylib', 'device', 'battery_utils_test.py'),
J('pylib', 'device', 'device_utils_test.py'),
J('pylib', 'device', 'logcat_monitor_test.py'),
J('pylib', 'gtest', 'gtest_test_instance_test.py'),
@@ -70,8 +52,6 @@
J('pylib', 'utils', 'md5sum_test.py'),
],
env=pylib_test_env))
- # TODO(jbudorick): Reenable this check once upstreaming is finished.
- # output.extend(_CheckDeletionsOnlyFiles(input_api, output_api))
return output
diff --git a/build/android/adb_install_apk.py b/build/android/adb_install_apk.py
index 5d0fd17..7bc634c 100755
--- a/build/android/adb_install_apk.py
+++ b/build/android/adb_install_apk.py
@@ -10,7 +10,6 @@
import os
import sys
-from pylib import android_commands
from pylib import constants
from pylib.device import device_utils
@@ -71,12 +70,13 @@
constants.SetBuildType(options.build_type)
ValidateInstallAPKOption(parser, options, args)
- devices = android_commands.GetAttachedDevices()
+ devices = device_utils.DeviceUtils.HealthyDevices()
if options.device:
- if options.device not in devices:
+ device_serials = [d.adb.GetDeviceSerial() for d in devices]
+ if options.device not in device_serials:
raise Exception('Error: %s not in attached devices %s' % (options.device,
- ','.join(devices)))
+ ','.join(device_serials)))
devices = [options.device]
if not devices:
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py
index 1958fdd..6cae0cf 100755
--- a/build/android/adb_reverse_forwarder.py
+++ b/build/android/adb_reverse_forwarder.py
@@ -11,12 +11,14 @@
to be built.
"""
+import logging
import optparse
import sys
import time
-from pylib import android_commands
-from pylib import constants, forwarder
+from pylib import constants
+from pylib import forwarder
+from pylib.device import adb_wrapper
from pylib.device import device_utils
from pylib.utils import run_tests_helper
@@ -51,19 +53,19 @@
parser.error('Bad port number')
sys.exit(1)
- devices = android_commands.GetAttachedDevices()
+ devices = device_utils.DeviceUtils.HealthyDevices()
if options.device:
- if options.device not in devices:
+ if options.device not in [str(d) for d in devices]:
raise Exception('Error: %s not in attached devices %s' % (options.device,
','.join(devices)))
devices = [options.device]
else:
if not devices:
raise Exception('Error: no connected devices')
- print "No device specified. Defaulting to " + devices[0]
+ logging.info('No device specified. Defaulting to %s', devices[0])
- device = device_utils.DeviceUtils(devices[0])
+ device = devices[0]
constants.SetBuildType(options.build_type)
try:
forwarder.Forwarder.Map(port_pairs, device)
diff --git a/build/android/android_exports.gyp b/build/android/android_exports.gyp
deleted file mode 100644
index bf3424d..0000000
--- a/build/android/android_exports.gyp
+++ /dev/null
@@ -1,43 +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.
-
-# This target is only used when android_webview_build==1 - it implements a
-# whitelist for exported symbols to minimise the binary size and prevent us
-# accidentally exposing things we don't mean to expose.
-
-{
- 'variables': {
- 'android_linker_script%': '<(SHARED_INTERMEDIATE_DIR)/android_webview_export_whitelist.lst',
- },
- 'targets': [
- {
- 'target_name': 'android_exports',
- 'type': 'none',
- 'inputs': [
- '<(DEPTH)/build/android/android_webview_export_whitelist.lst',
- ],
- 'outputs': [
- '<(android_linker_script)',
- ],
- 'copies': [
- {
- 'destination': '<(SHARED_INTERMEDIATE_DIR)',
- 'files': [
- '<@(_inputs)',
- ],
- },
- ],
- 'conditions': [
- ['component=="static_library"', {
- 'link_settings': {
- 'ldflags': [
- # Only export symbols that are specified in version script.
- '-Wl,--version-script=<(android_linker_script)',
- ],
- },
- }],
- ],
- },
- ],
-}
diff --git a/build/android/android_webview_export_whitelist.lst b/build/android/android_webview_export_whitelist.lst
deleted file mode 100644
index 2a56a75..0000000
--- a/build/android/android_webview_export_whitelist.lst
+++ /dev/null
@@ -1,16 +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.
-
-# Exports specification for android_webview_build==1, which uses a whitelist to
-# enforce only specific symbols being exported.
-# Check ld version script manual:
-# https://sourceware.org/binutils/docs-2.24/ld/VERSION.html#VERSION
-
-{
- global:
- Java_*_native*;
- JNI_OnLoad;
- __gcov_*;
- local: *;
-};
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 8561c01..8690a60 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -30,9 +30,14 @@
from pylib import android_commands
from pylib import constants
from pylib.cmd_helper import GetCmdOutput
+from pylib.device import battery_utils
from pylib.device import device_blacklist
+from pylib.device import device_errors
from pylib.device import device_list
from pylib.device import device_utils
+from pylib.utils import run_tests_helper
+
+_RE_DEVICE_ID = re.compile('Device ID = (\d+)')
def DeviceInfo(serial, options):
"""Gathers info on a device via various adb calls.
@@ -44,73 +49,62 @@
Tuple of device type, build id, report as a string, error messages, and
boolean indicating whether or not device can be used for testing.
"""
+ device = device_utils.DeviceUtils(serial)
+ battery = battery_utils.BatteryUtils(device)
- device_adb = device_utils.DeviceUtils(serial)
- device_type = device_adb.build_product
- device_build = device_adb.build_id
- device_build_type = device_adb.build_type
- device_product_name = device_adb.product_name
-
- try:
- battery_info = device_adb.old_interface.GetBatteryInfo()
- except Exception as e:
- battery_info = {}
- logging.error('Unable to obtain battery info for %s, %s', serial, e)
-
- def _GetData(re_expression, line, lambda_function=lambda x: x):
- if not line:
- return 'Unknown'
- found = re.findall(re_expression, line)
- if found and len(found):
- return lambda_function(found[0])
- return 'Unknown'
-
- battery_level = int(battery_info.get('level', 100))
- imei_slice = _GetData(r'Device ID = (\d+)',
- device_adb.old_interface.GetSubscriberInfo(),
- lambda x: x[-6:])
- json_data = {
- 'serial': serial,
- 'type': device_type,
- 'build': device_build,
- 'build_detail': device_adb.GetProp('ro.build.fingerprint'),
- 'battery': battery_info,
- 'imei_slice': imei_slice,
- 'wifi_ip': device_adb.GetProp('dhcp.wlan0.ipaddress'),
- }
- report = ['Device %s (%s)' % (serial, device_type),
- ' Build: %s (%s)' %
- (device_build, json_data['build_detail']),
- ' Current Battery Service state: ',
- '\n'.join([' %s: %s' % (k, v)
- for k, v in battery_info.iteritems()]),
- ' IMEI slice: %s' % imei_slice,
- ' Wifi IP: %s' % json_data['wifi_ip'],
- '']
-
+ battery_info = {}
+ battery_level = 100
errors = []
dev_good = True
- if battery_level < 15:
- errors += ['Device critically low in battery. Will add to blacklist.']
+ json_data = {
+ 'serial': serial,
+ 'type': device.build_product,
+ 'build': device.build_id,
+ 'build_detail': device.GetProp('ro.build.fingerprint'),
+ 'battery': {},
+ 'imei_slice': 'Unknown',
+ 'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'),
+ }
+
+ try:
+ try:
+ battery_info = battery.GetBatteryInfo(timeout=5)
+ battery_level = int(battery_info.get('level', battery_level))
+ json_data['battery'] = battery_info
+ except device_errors.CommandFailedError:
+ logging.exception('Failed to get battery information for %s', serial)
+
+ try:
+ for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'],
+ check_return=True, timeout=5):
+ m = _RE_DEVICE_ID.match(l)
+ if m:
+ json_data['imei_slice'] = m.group(1)[-6:]
+ except device_errors.CommandFailedError:
+ logging.exception('Failed to get IMEI slice for %s', serial)
+
+ if battery_level < 15:
+ errors += ['Device critically low in battery.']
+ dev_good = False
+ if not battery.GetCharging():
+ battery.SetCharging(True)
+ if not options.no_provisioning_check:
+ setup_wizard_disabled = (
+ device.GetProp('ro.setupwizard.mode') == 'DISABLED')
+ if not setup_wizard_disabled and device.build_type != 'user':
+ errors += ['Setup wizard not disabled. Was it provisioned correctly?']
+ if (device.product_name == 'mantaray' and
+ battery_info.get('AC powered', None) != 'true'):
+ errors += ['Mantaray device not connected to AC power.']
+ except device_errors.CommandFailedError:
+ logging.exception('Failure while getting device status.')
dev_good = False
- if not device_adb.old_interface.IsDeviceCharging():
- if device_adb.old_interface.CanControlUsbCharging():
- device_adb.old_interface.EnableUsbCharging()
- else:
- logging.error('Device %s is not charging' % serial)
- if not options.no_provisioning_check:
- setup_wizard_disabled = (
- device_adb.GetProp('ro.setupwizard.mode') == 'DISABLED')
- if not setup_wizard_disabled and device_build_type != 'user':
- errors += ['Setup wizard not disabled. Was it provisioned correctly?']
- if (device_product_name == 'mantaray' and
- battery_info.get('AC powered', None) != 'true'):
- errors += ['Mantaray device not connected to AC power.']
+ except device_errors.CommandTimeoutError:
+ logging.exception('Timeout while getting device status.')
+ dev_good = False
- full_report = '\n'.join(report)
-
- return (device_type, device_build, battery_level, full_report, errors,
- dev_good, json_data)
+ return (device.build_product, device.build_id, battery_level, errors,
+ dev_good, json_data)
def CheckForMissingDevices(options, adb_online_devs):
@@ -122,11 +116,6 @@
adb_online_devs: A list of serial numbers of the currently visible
and online attached devices.
"""
- # TODO(navabi): remove this once the bug that causes different number
- # of devices to be detected between calls is fixed.
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
-
out_dir = os.path.abspath(options.out_dir)
# last_devices denotes all known devices prior to this run
@@ -189,10 +178,10 @@
os.environ.get('BUILDBOT_SLAVENAME'),
os.environ.get('BUILDBOT_BUILDNUMBER')))))
return ['Current online devices: %s' % adb_online_devs,
- '%s are no longer visible. Were they removed?\n' % missing_devs,
- 'SHERIFF:\n',
- '@@@STEP_LINK@Click here to file a bug@%s@@@\n' % crbug_link,
- 'Cache file: %s\n\n' % last_devices_path,
+ '%s are no longer visible. Were they removed?' % missing_devs,
+ 'SHERIFF:',
+ '@@@STEP_LINK@Click here to file a bug@%s@@@' % crbug_link,
+ 'Cache file: %s' % last_devices_path,
'adb devices: %s' % GetCmdOutput(['adb', 'devices']),
'adb devices(GetAttachedDevices): %s' % adb_online_devs]
else:
@@ -201,8 +190,9 @@
bb_annotations.PrintWarning()
bb_annotations.PrintSummaryText(
'%d new devices detected' % len(new_devs))
- print ('New devices detected %s. And now back to your '
- 'regularly scheduled program.' % list(new_devs))
+ logging.info('New devices detected:')
+ for d in new_devs:
+ logging.info(' %s', d)
def SendEmail(from_address, to_addresses, cc_addresses, subject, msg):
@@ -214,20 +204,20 @@
server = smtplib.SMTP('localhost')
server.sendmail(from_address, to_addresses, msg_body)
server.quit()
- except Exception as e:
- print 'Failed to send alert email. Error: %s' % e
+ except Exception:
+ logging.exception('Failed to send alert email.')
def RestartUsb():
if not os.path.isfile('/usr/bin/restart_usb'):
- print ('ERROR: Could not restart usb. /usr/bin/restart_usb not installed '
- 'on host (see BUG=305769).')
+ logging.error('Could not restart usb. ''/usr/bin/restart_usb not '
+ 'installed on host (see BUG=305769).')
return False
lsusb_proc = bb_utils.SpawnCmd(['lsusb'], stdout=subprocess.PIPE)
lsusb_output, _ = lsusb_proc.communicate()
if lsusb_proc.returncode:
- print 'Error: Could not get list of USB ports (i.e. lsusb).'
+ logging.error('Could not get list of USB ports (i.e. lsusb).')
return lsusb_proc.returncode
usb_devices = [re.findall(r'Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0]
@@ -243,10 +233,11 @@
if dev != '001':
return_code = bb_utils.RunCmd(['/usr/bin/restart_usb', bus, dev])
if return_code:
- print 'Error restarting USB device /dev/bus/usb/%s/%s' % (bus, dev)
+ logging.error('Error restarting USB device /dev/bus/usb/%s/%s',
+ bus, dev)
all_restarted = False
else:
- print 'Restarted USB device /dev/bus/usb/%s/%s' % (bus, dev)
+ logging.info('Restarted USB device /dev/bus/usb/%s/%s', bus, dev)
return all_restarted
@@ -263,14 +254,15 @@
for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]:
for p in GetAllAdb():
try:
- print 'kill %d %d (%s [%s])' % (sig, p.pid, p.name,
- ' '.join(p.cmdline))
+ logging.info('kill %d %d (%s [%s])', sig, p.pid, p.name,
+ ' '.join(p.cmdline))
p.send_signal(sig)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
for p in GetAllAdb():
try:
- print 'Unable to kill %d (%s [%s])' % (p.pid, p.name, ' '.join(p.cmdline))
+ logging.error('Unable to kill %d (%s [%s])', p.pid, p.name,
+ ' '.join(p.cmdline))
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
@@ -288,11 +280,15 @@
help='Restart USB ports before running device check.')
parser.add_option('--json-output',
help='Output JSON information into a specified file.')
+ parser.add_option('-v', '--verbose', action='count', default=1,
+ help='Log more information.')
options, args = parser.parse_args()
if args:
parser.error('Unknown options %s' % args)
+ run_tests_helper.SetLogLevel(options.verbose)
+
# Remove the last build's "bad devices" before checking device statuses.
device_blacklist.ResetBlacklist()
@@ -304,7 +300,8 @@
devices = android_commands.GetAttachedDevices()
# Only restart usb if devices are missing.
if set(expected_devices) != set(devices):
- print 'expected_devices: %s, devices: %s' % (expected_devices, devices)
+ logging.warning('expected_devices: %s', expected_devices)
+ logging.warning('devices: %s', devices)
KillAllAdb()
retries = 5
usb_restarted = True
@@ -312,9 +309,10 @@
if not RestartUsb():
usb_restarted = False
bb_annotations.PrintWarning()
- print 'USB reset stage failed, wait for any device to come back.'
+ logging.error('USB reset stage failed, '
+ 'wait for any device to come back.')
while retries:
- print 'retry adb devices...'
+ logging.info('retry adb devices...')
time.sleep(1)
devices = android_commands.GetAttachedDevices()
if set(expected_devices) == set(devices):
@@ -330,10 +328,10 @@
offline_devices = android_commands.GetAttachedDevices(
hardware=False, emulator=False, offline=True)
- types, builds, batteries, reports, errors, json_data = [], [], [], [], [], []
- fail_step_lst = []
+ types, builds, batteries, errors, devices_ok, json_data = (
+ [], [], [], [], [], [])
if devices:
- types, builds, batteries, reports, errors, fail_step_lst, json_data = (
+ types, builds, batteries, errors, devices_ok, json_data = (
zip(*[DeviceInfo(dev, options) for dev in devices]))
# Write device info to file for buildbot info display.
@@ -354,7 +352,16 @@
bb_annotations.PrintMsg('Online devices: %d. Device types %s, builds %s'
% (len(devices), unique_types, unique_builds))
- print '\n'.join(reports)
+
+ for j in json_data:
+ logging.info('Device %s (%s)', j.get('serial'), j.get('type'))
+ logging.info(' Build: %s (%s)', j.get('build'), j.get('build_detail'))
+ logging.info(' Current Battery Service state:')
+ for k, v in j.get('battery', {}).iteritems():
+ logging.info(' %s: %s', k, v)
+ logging.info(' IMEI slice: %s', j.get('imei_slice'))
+ logging.info(' WiFi IP: %s', j.get('wifi_ip'))
+
for serial, dev_errors in zip(devices, errors):
if dev_errors:
@@ -363,14 +370,14 @@
if err_msg:
bb_annotations.PrintWarning()
- msg = '\n'.join(err_msg)
- print msg
+ for e in err_msg:
+ logging.error(e)
from_address = 'buildbot@chromium.org'
to_addresses = ['chromium-android-device-alerts@google.com']
bot_name = os.environ.get('BUILDBOT_BUILDERNAME')
slave_name = os.environ.get('BUILDBOT_SLAVENAME')
subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name)
- SendEmail(from_address, to_addresses, [], subject, msg)
+ SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg))
if options.device_status_dashboard:
perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices',
@@ -388,8 +395,9 @@
f.write(json.dumps(json_data, indent=4))
num_failed_devs = 0
- for fail_status, device in zip(fail_step_lst, devices):
- if not fail_status:
+ for device_ok, device in zip(devices_ok, devices):
+ if not device_ok:
+ logging.warning('Blacklisting %s', str(device))
device_blacklist.ExtendBlacklist([str(device)])
num_failed_devs += 1
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index c9be13a..e5df563 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -94,9 +94,10 @@
'ChromeDriverWebViewShell.apk',
'org.chromium.chromedriver_webview_shell')]))
-VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'gpu',
- 'telemetry_unittests', 'telemetry_perf_unittests', 'ui',
- 'unit', 'webkit', 'webkit_layout', 'python_unittests'])
+VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'components_browsertests',
+ 'gpu', 'python_unittests', 'telemetry_unittests',
+ 'telemetry_perf_unittests', 'ui', 'unit', 'webkit',
+ 'webkit_layout'])
RunCmd = bb_utils.RunCmd
@@ -172,7 +173,7 @@
bb_annotations.PrintNamedStep(suite)
cmd = [suite] + args
cmd += suites_options.get(suite, [])
- if suite == 'content_browsertests':
+ if suite == 'content_browsertests' or suite == 'components_browsertests':
cmd.append('--num_retries=1')
_RunTest(options, cmd, suite)
@@ -315,7 +316,7 @@
'--build-name', options.build_properties.get('buildername', ''),
'--platform=android']
- for flag in 'test_results_server', 'driver_name', 'additional_drt_flag':
+ for flag in 'test_results_server', 'driver_name', 'additional_driver_flag':
if flag in options.factory_properties:
cmd_args.extend(['--%s' % flag.replace('_', '-'),
options.factory_properties.get(flag)])
@@ -557,6 +558,8 @@
return [
('chromedriver', RunChromeDriverTests),
('chrome_proxy', RunChromeProxyTests),
+ ('components_browsertests',
+ lambda options: RunTestSuites(options, ['components_browsertests'])),
('gpu', RunGPUTests),
('python_unittests', RunPythonUnitTests),
('telemetry_unittests', RunTelemetryUnitTests),
diff --git a/build/android/buildbot/bb_host_steps.py b/build/android/buildbot/bb_host_steps.py
index 4041ccd..1e927fb 100755
--- a/build/android/buildbot/bb_host_steps.py
+++ b/build/android/buildbot/bb_host_steps.py
@@ -4,6 +4,7 @@
# found in the LICENSE file.
import os
+import json
import sys
import bb_utils
@@ -14,7 +15,7 @@
SLAVE_SCRIPTS_DIR = os.path.join(bb_utils.BB_BUILD_DIR, 'scripts', 'slave')
-VALID_HOST_TESTS = set(['check_webview_licenses', 'findbugs'])
+VALID_HOST_TESTS = set(['check_webview_licenses'])
DIR_BUILD_ROOT = os.path.dirname(constants.DIR_SOURCE_ROOT)
@@ -78,17 +79,6 @@
+ bb_utils.EncodeProperties(options), cwd=DIR_BUILD_ROOT)
-def FindBugs(options):
- bb_annotations.PrintNamedStep('findbugs')
- build_type = []
- if options.target == 'Release':
- build_type = ['--release-build']
- RunCmd([SrcPath('build', 'android', 'findbugs_diff.py')] + build_type)
- RunCmd([SrcPath(
- 'tools', 'android', 'findbugs_plugin', 'test',
- 'run_findbugs_plugin_tests.py')] + build_type)
-
-
def BisectPerfRegression(options):
args = []
if options.extra_src:
@@ -96,7 +86,9 @@
RunCmd([SrcPath('tools', 'prepare-bisect-perf-regression.py'),
'-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)])
RunCmd([SrcPath('tools', 'run-bisect-perf-regression.py'),
- '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)] + args)
+ '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir),
+ '--build-properties=%s' % json.dumps(options.build_properties)] +
+ args)
def GetHostStepCmds():
@@ -105,7 +97,6 @@
('extract_build', ExtractBuild),
('check_webview_licenses', CheckWebViewLicenses),
('bisect_perf_regression', BisectPerfRegression),
- ('findbugs', FindBugs),
('zip_build', ZipBuild)
]
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 29cce1b..a6afb86 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -117,8 +117,7 @@
compile_step = ['compile']
chrome_proxy_tests = ['chrome_proxy']
python_unittests = ['python_unittests']
- std_host_tests = ['check_webview_licenses', 'findbugs']
- emma_coverage_tests = [x for x in std_host_tests if x is not 'findbugs']
+ std_host_tests = ['check_webview_licenses']
std_build_steps = ['compile', 'zip_build']
std_test_steps = ['extract_build']
std_tests = ['ui', 'unit']
@@ -164,7 +163,7 @@
B('fyi-x86-builder-dbg',
H(compile_step + std_host_tests, experimental, target_arch='ia32')),
B('fyi-builder-dbg',
- H(std_build_steps + emma_coverage_tests, experimental,
+ H(std_build_steps + std_host_tests, experimental,
extra_gyp='emma_coverage=1')),
B('x86-builder-dbg',
H(compile_step + std_host_tests, target_arch='ia32')),
@@ -175,7 +174,7 @@
'--coverage-bucket', CHROMIUM_COVERAGE_BUCKET,
'--cleanup'])),
B('user-build-fyi-tests-dbg', H(std_test_steps),
- T(telemetry_tests_user_build)),
+ T(telemetry_tests_user_build + ['components_browsertests'])),
B('fyi-component-builder-tests-dbg',
H(compile_step, extra_gyp='component=shared_library'),
T(std_tests, ['--experimental', flakiness_server])),
diff --git a/build/android/cpufeatures.gypi b/build/android/cpufeatures.gypi
index b7b0b53..672ff1f 100644
--- a/build/android/cpufeatures.gypi
+++ b/build/android/cpufeatures.gypi
@@ -2,30 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# Depend on the Android NDK's cpu feature detection. The WebView build is part
-# of the system and the library already exists; for the normal build there is a
-# gyp file in the checked-in NDK to build it.
+# Depend on the Android NDK's cpu feature detection. This additional level of
+# abstraction is no longer necessary and targets can depend directly on
+# build/android/ndk.gyp:cpu_features instead.
+# TODO(torne): delete this once all DEPS have been rolled to not use it.
+# http://crbug.com/440793
{
- 'conditions': [
- ['android_webview_build == 1', {
- # This is specified twice intentionally: Android provides include paths
- # to targets automatically if they depend on libraries, so we add this
- # library to every target that includes this .gypi to make the headers
- # available, then also add it to targets that link those targets via
- # link_settings to ensure it ends up being linked even if the main target
- # doesn't include this .gypi.
- 'libraries': [
- 'cpufeatures.a',
- ],
- 'link_settings': {
- 'libraries': [
- 'cpufeatures.a',
- ],
- },
- }, {
- 'dependencies': [
- '<(DEPTH)/build/android/ndk.gyp:cpu_features',
- ],
- }],
+ 'dependencies': [
+ '<(DEPTH)/build/android/ndk.gyp:cpu_features',
],
}
diff --git a/build/android/enable_asserts.py b/build/android/enable_asserts.py
index 0e30bc2..8fb7dca 100755
--- a/build/android/enable_asserts.py
+++ b/build/android/enable_asserts.py
@@ -6,33 +6,37 @@
"""Enables dalvik vm asserts in the android device."""
-from pylib import android_commands
-from pylib.device import device_utils
-import optparse
+import argparse
import sys
+from pylib.device import device_utils
-def main(argv):
- option_parser = optparse.OptionParser()
- option_parser.add_option('--enable_asserts', dest='set_asserts',
- action='store_true', default=None,
+
+def main():
+ parser = argparse.ArgumentParser()
+
+ set_asserts_group = parser.add_mutually_exclusive_group(required=True)
+ set_asserts_group.add_argument(
+ '--enable_asserts', dest='set_asserts', action='store_true',
help='Sets the dalvik.vm.enableassertions property to "all"')
- option_parser.add_option('--disable_asserts', dest='set_asserts',
- action='store_false', default=None,
+ set_asserts_group.add_argument(
+ '--disable_asserts', dest='set_asserts', action='store_false',
help='Removes the dalvik.vm.enableassertions property')
- options, _ = option_parser.parse_args(argv)
+
+ args = parser.parse_args()
# TODO(jbudorick): Accept optional serial number and run only for the
# specified device when present.
- devices = android_commands.GetAttachedDevices()
- for device in [device_utils.DeviceUtils(serial) for serial in devices]:
- if options.set_asserts != None:
- if device.SetJavaAsserts(options.set_asserts):
- # TODO(jbudorick) How to best do shell restarts after the
- # android_commands refactor?
- device.RunShellCommand('stop')
- device.RunShellCommand('start')
+ devices = device_utils.DeviceUtils.parallel()
+
+ def set_java_asserts_and_restart(device):
+ if device.SetJavaAsserts(args.set_asserts):
+ device.RunShellCommand('stop')
+ device.RunShellCommand('start')
+
+ devices.pMap(set_java_asserts_and_restart)
+ return 0
if __name__ == '__main__':
- main(sys.argv)
+ sys.exit(main())
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 9934c1a..bdf9966 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -22,16 +22,8 @@
'keystore_path%': '<(DEPTH)/build/android/ant/chromium-debug.keystore',
'keystore_name%': 'chromiumdebugkey',
'keystore_password%': 'chromium',
- 'conditions': [
- # Webview doesn't use zipalign or rezip_apk_jar.
- ['android_webview_build==0', {
- 'zipalign_path%': '<(android_sdk_tools)/zipalign',
- 'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar'
- }, {
- 'zipalign_path%': "",
- 'rezip_apk_jar_path%': "",
- }],
- ],
+ 'zipalign_path%': '<(android_sdk_tools)/zipalign',
+ 'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar',
},
'inputs': [
'<(DEPTH)/build/android/gyp/finalize_apk.py',
diff --git a/build/android/findbugs_action.gypi b/build/android/findbugs_action.gypi
new file mode 100644
index 0000000..e3b3d36
--- /dev/null
+++ b/build/android/findbugs_action.gypi
@@ -0,0 +1,22 @@
+
+{
+ 'action_name': 'findbugs_<(_target_name)',
+ 'message': 'Running findbugs on <(_target_name)',
+ 'variables': {
+ },
+ 'inputs': [
+ '<(DEPTH)/build/android/findbugs_diff.py',
+ '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+ '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+ '<(findbugs_target_jar_path)',
+ ],
+ 'outputs': [
+ '<(stamp_path)',
+ ],
+ 'action': [
+ 'python', '<(DEPTH)/build/android/findbugs_diff.py',
+ '--auxclasspath-gyp', '>(auxclasspath)',
+ '--stamp', '<(stamp_path)',
+ '<(findbugs_target_jar_path)',
+ ],
+}
diff --git a/build/android/findbugs_diff.py b/build/android/findbugs_diff.py
index 28224f1..f55e462 100755
--- a/build/android/findbugs_diff.py
+++ b/build/android/findbugs_diff.py
@@ -5,14 +5,6 @@
# found in the LICENSE file.
"""Runs findbugs, and returns an error code if there are new warnings.
-This runs findbugs with an additional flag to exclude known bugs.
-To update the list of known bugs, do this:
-
- findbugs_diff.py --rebaseline
-
-Note that this is separate from findbugs_exclude.xml. The "exclude" file has
-false positives that we do not plan to fix. The "known bugs" file has real
-bugs that we *do* plan to fix (but haven't done so yet).
Other options
--only-analyze used to only analyze the class you are interested.
@@ -20,30 +12,99 @@
--findbugs-args used to passin other findbugs's options.
Run
- $CHROM_SRC/third_party/findbugs/bin/findbugs -textui for details.
+ $CHROMIUM_SRC/third_party/findbugs/bin/findbugs -textui for details.
"""
+import argparse
import os
import sys
from pylib import constants
from pylib.utils import findbugs
+_DEFAULT_BASE_DIR = os.path.join(
+ constants.DIR_SOURCE_ROOT, 'build', 'android', 'findbugs_filter')
+
+sys.path.append(
+ os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'gyp'))
+from util import build_utils
+
def main():
- parser = findbugs.GetCommonParser()
+ parser = argparse.ArgumentParser()
- options, _ = parser.parse_args()
+ parser.add_argument(
+ '-a', '--auxclasspath', default=None, dest='auxclasspath',
+ help='Set aux classpath for analysis.')
+ parser.add_argument(
+ '--auxclasspath-gyp', dest='auxclasspath_gyp',
+ help='A gyp list containing the aux classpath for analysis')
+ parser.add_argument(
+ '-o', '--only-analyze', default=None,
+ dest='only_analyze', help='Only analyze the given classes and packages.')
+ parser.add_argument(
+ '-e', '--exclude', default=None, dest='exclude',
+ help='Exclude bugs matching given filter.')
+ parser.add_argument(
+ '-l', '--release-build', action='store_true', dest='release_build',
+ help='Analyze release build instead of debug.')
+ parser.add_argument(
+ '-f', '--findbug-args', default=None, dest='findbug_args',
+ help='Additional findbug arguments.')
+ parser.add_argument(
+ '-b', '--base-dir', default=_DEFAULT_BASE_DIR,
+ dest='base_dir', help='Base directory for configuration file.')
+ parser.add_argument(
+ '--output-file', dest='output_file',
+ help='Path to save the output to.')
+ parser.add_argument(
+ '--stamp', help='Path to touch on success.')
+ parser.add_argument(
+ '--depfile', help='Path to the depfile. This must be specified as the '
+ "action's first output.")
- if not options.base_dir:
- options.base_dir = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
- 'android', 'findbugs_filter')
- if not options.only_analyze:
- options.only_analyze = 'org.chromium.-'
+ parser.add_argument(
+ 'jar_paths', metavar='JAR_PATH', nargs='+',
+ help='JAR file to analyze')
- return findbugs.Run(options)
+ args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:]))
+ if args.auxclasspath:
+ args.auxclasspath = args.auxclasspath.split(':')
+ elif args.auxclasspath_gyp:
+ args.auxclasspath = build_utils.ParseGypList(args.auxclasspath_gyp)
+
+ if args.base_dir:
+ if not args.exclude:
+ args.exclude = os.path.join(args.base_dir, 'findbugs_exclude.xml')
+
+ findbugs_command, findbugs_warnings = findbugs.Run(
+ args.exclude, args.only_analyze, args.auxclasspath,
+ args.output_file, args.findbug_args, args.jar_paths)
+
+ if findbugs_warnings:
+ print
+ print '*' * 80
+ print 'FindBugs run via:'
+ print findbugs_command
+ print
+ print 'FindBugs reported the following issues:'
+ for warning in sorted(findbugs_warnings):
+ print str(warning)
+ print '*' * 80
+ print
+ else:
+ if args.depfile:
+ build_utils.WriteDepfile(
+ args.depfile,
+ build_utils.GetPythonDependencies() + args.auxclasspath
+ + args.jar_paths)
+ if args.stamp:
+ build_utils.Touch(args.stamp)
+
+ return len(findbugs_warnings)
if __name__ == '__main__':
sys.exit(main())
+
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index 5060e47..dbff9d9 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -12,40 +12,12 @@
<FindBugsFilter>
<!-- Skip the generated resource classes (including nested classes). -->
<Match>
- <Class name="~org\.chromium\..*\.R(\$\w+)?" />
+ <Class name="~.*\.R(\$\w+)?" />
</Match>
<Match>
<Class name="~org\.chromium\..*\.Manifest(\$\w+)?" />
</Match>
+ <Bug pattern="DM_STRING_CTOR" />
<!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
- <Match>
- <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
- <Method name="onCancel" />
- <Bug code="Dm" />
- </Match>
- <Match>
- <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
- <Method name="onClick" />
- <Bug code="Dm" />
- </Match>
<Bug pattern="DM_DEFAULT_ENCODING" />
- <!-- Ignore bugs that are often false-positives in test code -->
- <Match>
- <Class name="~org\.chromium\..*Test(\$\w+)?" />
- <Or>
- <Bug code="DLS,UrF" />
- <Bug pattern="DM_GC" />
- </Or>
- </Match>
- <!--
- crbug.com/449101
- Ignore findbugs plugin test cases.
- -->
- <Match>
- <Or>
- <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedMethod" />
- <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedStaticMethod" />
- <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedThis" />
- </Or>
- </Match>
</FindBugsFilter>
diff --git a/build/android/gyp/jarjar_resources.py b/build/android/gyp/jarjar_resources.py
deleted file mode 100755
index 67b510b..0000000
--- a/build/android/gyp/jarjar_resources.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Transforms direct Java class references in Android layout .xml files
-according to the specified JarJar rules."""
-
-import optparse
-import os
-import shutil
-import sys
-from xml.dom import minidom
-
-from util import build_utils
-
-
-class JarJarRules(object):
- def __init__(self, jarjar_rules):
- self._rules = []
- for line in jarjar_rules.splitlines():
- rule = line.split()
- if rule[0] != 'rule':
- continue
- _, src, dest = rule
- if src.endswith('**'):
- src_real_name = src[:-2]
- else:
- assert not '*' in src
- src_real_name = src
-
- if dest.endswith('@0'):
- self._rules.append((src, dest[:-2] + src_real_name))
- elif dest.endswith('@1'):
- assert '**' in src
- self._rules.append((src, dest[:-2]))
- else:
- assert not '@' in dest
- self._rules.append((src, dest))
-
- def RenameClass(self, class_name):
- for old, new in self._rules:
- if old.endswith('**') and old[:-2] in class_name:
- return class_name.replace(old[:-2], new, 1)
- if '*' not in old and class_name.endswith(old):
- return class_name.replace(old, new, 1)
- return class_name
-
-
-def RenameNodes(node, rules):
- if node.nodeType == node.ELEMENT_NODE:
- if node.tagName.lower() == 'view' and node.attributes.has_key('class'):
- node.attributes['class'] = rules.RenameClass(node.attributes['class'])
- else:
- node.tagName = rules.RenameClass(node.tagName)
- for child in node.childNodes:
- RenameNodes(child, rules)
-
-
-def ProcessLayoutFile(path, rules):
- xmldoc = minidom.parse(path)
- RenameNodes(xmldoc.documentElement, rules)
- with open(path, 'w') as f:
- xmldoc.writexml(f)
-
-
-def LayoutFilesFilter(src, names):
- if os.path.basename(src).lower() != 'layout':
- return []
- else:
- return filter(lambda n: n.endswith('.xml'), names)
-
-
-def ProcessResources(options):
- with open(options.rules_path) as f:
- rules = JarJarRules(f.read())
-
- build_utils.DeleteDirectory(options.output_dir)
- for input_dir in options.input_dir:
- shutil.copytree(input_dir, options.output_dir)
-
- for root, _dirnames, filenames in os.walk(options.output_dir):
- layout_files = LayoutFilesFilter(root, filenames)
- for layout_file in layout_files:
- ProcessLayoutFile(os.path.join(root, layout_file), rules)
-
-
-def ParseArgs():
- parser = optparse.OptionParser()
- parser.add_option('--input-dir', action='append',
- help='Path to the resources folder to process.')
- parser.add_option('--output-dir',
- help=('Directory to hold processed resources. Note: the ' +
- 'directory will be clobbered on every invocation.'))
- parser.add_option('--rules-path',
- help='Path to the jarjar rules file.')
- parser.add_option('--stamp', help='Path to touch on success.')
-
- options, args = parser.parse_args()
-
- if args:
- parser.error('No positional arguments should be given.')
-
- # Check that required options have been provided.
- required_options = ('input_dir', 'output_dir', 'rules_path')
- build_utils.CheckOptions(options, parser, required=required_options)
-
- return options
-
-
-def main():
- options = ParseArgs()
-
- ProcessResources(options)
-
- if options.stamp:
- build_utils.Touch(options.stamp)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/android/gyp/jinja_template.py b/build/android/gyp/jinja_template.py
index 9e9705c..6653f21 100755
--- a/build/android/gyp/jinja_template.py
+++ b/build/android/gyp/jinja_template.py
@@ -34,15 +34,17 @@
return list(self.loaded_templates)
-def ProcessFile(env, input_filename, output_filename, variables):
- input_rel_path = os.path.relpath(input_filename, build_utils.CHROMIUM_SRC)
+def ProcessFile(env, input_filename, loader_base_dir, output_filename,
+ variables):
+ input_rel_path = os.path.relpath(input_filename, loader_base_dir)
template = env.get_template(input_rel_path)
output = template.render(variables)
with codecs.open(output_filename, 'w', 'utf-8') as output_file:
output_file.write(output)
-def ProcessFiles(env, input_filenames, inputs_base_dir, outputs_zip, variables):
+def ProcessFiles(env, input_filenames, loader_base_dir, inputs_base_dir,
+ outputs_zip, variables):
with build_utils.TempDir() as temp_dir:
for input_filename in input_filenames:
relpath = os.path.relpath(os.path.abspath(input_filename),
@@ -54,7 +56,8 @@
output_filename = os.path.join(temp_dir, relpath)
parent_dir = os.path.dirname(output_filename)
build_utils.MakeDirectory(parent_dir)
- ProcessFile(env, input_filename, output_filename, variables)
+ ProcessFile(env, input_filename, loader_base_dir, output_filename,
+ variables)
build_utils.ZipDir(outputs_zip, temp_dir)
@@ -71,6 +74,10 @@
'the inputs. Each output\'s path in the output zip will '
'match the relative path from INPUTS_BASE_DIR to the '
'input. Required if --output-zip is given.')
+ parser.add_option('--loader-base-dir', help='Base path used by the template '
+ 'loader. Must be a common ancestor directory of '
+ 'the inputs. Defaults to CHROMIUM_SRC.',
+ default=build_utils.CHROMIUM_SRC)
parser.add_option('--variables', help='Variables to be made available in the '
'template processing environment, as a GYP list (e.g. '
'--variables "channel=beta mstone=39")', default='')
@@ -95,14 +102,15 @@
name, _, value = v.partition('=')
variables[name] = value
- loader = RecordingFileSystemLoader(build_utils.CHROMIUM_SRC)
+ loader = RecordingFileSystemLoader(options.loader_base_dir)
env = jinja2.Environment(loader=loader, undefined=jinja2.StrictUndefined,
line_comment_prefix='##')
if options.output:
- ProcessFile(env, inputs[0], options.output, variables)
+ ProcessFile(env, inputs[0], options.loader_base_dir, options.output,
+ variables)
else:
- ProcessFiles(env, inputs, options.inputs_base_dir, options.outputs_zip,
- variables)
+ ProcessFiles(env, inputs, options.loader_base_dir, options.inputs_base_dir,
+ options.outputs_zip, variables)
if options.depfile:
deps = loader.get_loaded_templates() + build_utils.GetPythonDependencies()
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 52cf143..4e6c27d 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -10,6 +10,7 @@
(see generate_v14_compatible_resources.py).
"""
+import codecs
import optparse
import os
import re
@@ -112,14 +113,15 @@
if len(java_files) != 1:
return
r_java_file = java_files[0]
- r_java_contents = open(r_java_file).read()
+ r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
for package in extra_packages:
package_r_java_dir = os.path.join(r_dir, *package.split('.'))
build_utils.MakeDirectory(package_r_java_dir)
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
- open(package_r_java_path, 'w').write(
- re.sub(r'package [.\w]*;', 'package %s;' % package, r_java_contents))
+ new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
+ r_java_contents)
+ codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
# TODO(cjhopman): These extra package's R.java files should be filtered to
# only contain the resources listed in their R.txt files. At this point, we
# have already compiled those other libraries, so doing this would only
diff --git a/build/android/gyp/util/build_device.py b/build/android/gyp/util/build_device.py
index b153a15..7e0d57b 100644
--- a/build/android/gyp/util/build_device.py
+++ b/build/android/gyp/util/build_device.py
@@ -40,7 +40,7 @@
return self.id
def Install(self, *args, **kwargs):
- return self.device.old_interface.Install(*args, **kwargs)
+ return self.device.Install(*args, **kwargs)
def GetInstallMetadata(self, apk_package):
"""Gets the metadata on the device for the apk_package apk."""
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index a0cd7c1..65b1a64 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -24,7 +24,7 @@
'third_party', 'colorama', 'src')
# aapt should ignore OWNERS files in addition the default ignore pattern.
AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' +
- '!CVS:!thumbs.db:!picasa.ini:!*~')
+ '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp')
@contextlib.contextmanager
@@ -236,6 +236,7 @@
def MergeZips(output, inputs, exclude_patterns=None):
+ added_names = set()
def Allow(name):
if exclude_patterns is not None:
for p in exclude_patterns:
@@ -247,8 +248,9 @@
for in_file in inputs:
with zipfile.ZipFile(in_file, 'r') as in_zip:
for name in in_zip.namelist():
- if Allow(name):
+ if name not in added_names and Allow(name):
out_zip.writestr(name, in_zip.read(name))
+ added_names.add(name)
def PrintWarning(message):
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 5fc8955..1b4379d 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -29,11 +29,43 @@
import optparse
import os
import sys
+import xml.dom.minidom
from util import build_utils
import write_ordered_libraries
+class AndroidManifest(object):
+ def __init__(self, path):
+ self.path = path
+ dom = xml.dom.minidom.parse(path)
+ manifests = dom.getElementsByTagName('manifest')
+ assert len(manifests) == 1
+ self.manifest = manifests[0]
+
+ def GetInstrumentation(self):
+ instrumentation_els = self.manifest.getElementsByTagName('instrumentation')
+ if len(instrumentation_els) == 0:
+ return None
+ if len(instrumentation_els) != 1:
+ raise Exception(
+ 'More than one <instrumentation> element found in %s' % self.path)
+ return instrumentation_els[0]
+
+ def CheckInstrumentation(self, expected_package):
+ instr = self.GetInstrumentation()
+ if not instr:
+ raise Exception('No <instrumentation> elements found in %s' % self.path)
+ instrumented_package = instr.getAttributeNS(
+ 'http://schemas.android.com/apk/res/android', 'targetPackage')
+ if instrumented_package != expected_package:
+ raise Exception(
+ 'Wrong instrumented package. Expected %s, got %s'
+ % (expected_package, instrumented_package))
+
+ def GetPackageName(self):
+ return self.manifest.getAttribute('package')
+
dep_config_cache = {}
def GetDepConfig(path):
@@ -88,6 +120,10 @@
parser.add_option('--native-libs', help='List of top-level native libs.')
parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.')
+ parser.add_option('--tested-apk-config',
+ help='Path to the build config of the tested apk (for an instrumentation '
+ 'test apk).')
+
options, args = parser.parse_args(argv)
if args:
@@ -154,7 +190,6 @@
}
deps_info = config['deps_info']
-
if options.type == 'java_library' and not options.bypass_platform_checks:
deps_info['requires_android'] = options.requires_android
deps_info['supports_android'] = options.supports_android
@@ -172,7 +207,6 @@
raise Exception('Not all deps support the Android platform: ' +
str(deps_not_support_android))
-
if options.type in ['java_library', 'android_apk']:
javac_classpath = [c['jar_path'] for c in direct_library_deps]
java_full_classpath = [c['jar_path'] for c in all_library_deps]
@@ -216,14 +250,31 @@
config['resources']['extra_package_names'] = [
c['package_name'] for c in all_resources_deps if 'package_name' in c]
+ if options.type in ['android_apk', 'deps_dex']:
+ deps_dex_files = [c['dex_path'] for c in all_library_deps]
+
+ # An instrumentation test apk should exclude the dex files that are in the apk
+ # under test.
+ if options.type == 'android_apk' and options.tested_apk_config:
+ tested_apk_config_paths = GetAllDepsConfigsInOrder(
+ [options.tested_apk_config])
+ tested_apk_configs = [GetDepConfig(p) for p in tested_apk_config_paths]
+ tested_apk_library_deps = DepsOfType('java_library', tested_apk_configs)
+ tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps]
+ deps_dex_files = [
+ p for p in deps_dex_files if not p in tested_apk_deps_dex_files]
+
+ tested_apk_config = GetDepConfig(options.tested_apk_config)
+ expected_tested_package = tested_apk_config['package_name']
+ AndroidManifest(options.android_manifest).CheckInstrumentation(
+ expected_tested_package)
# Dependencies for the final dex file of an apk or a 'deps_dex'.
if options.type in ['android_apk', 'deps_dex']:
config['final_dex'] = {}
dex_config = config['final_dex']
# TODO(cjhopman): proguard version
- dex_deps_files = [c['dex_path'] for c in all_library_deps]
- dex_config['dependency_dex_files'] = dex_deps_files
+ dex_config['dependency_dex_files'] = deps_dex_files
if options.type == 'android_apk':
config['dist_jar'] = {
@@ -231,6 +282,11 @@
c['jar_path'] for c in all_library_deps
]
}
+ manifest = AndroidManifest(options.android_manifest)
+ deps_info['package_name'] = manifest.GetPackageName()
+ if not options.tested_apk_config and manifest.GetInstrumentation():
+ # This must then have instrumentation only for itself.
+ manifest.CheckInstrumentation(manifest.GetPackageName())
library_paths = []
java_libraries_list = []
diff --git a/build/android/host_heartbeat.py b/build/android/host_heartbeat.py
index 429fca9..6a7cdd1 100755
--- a/build/android/host_heartbeat.py
+++ b/build/android/host_heartbeat.py
@@ -12,7 +12,6 @@
import sys
import time
-from pylib import android_commands
from pylib.device import device_utils
PULSE_PERIOD = 20
@@ -20,10 +19,10 @@
def main():
while True:
try:
- devices = android_commands.GetAttachedDevices()
- for device_serial in devices:
- device_utils.DeviceUtils(device_serial).RunShellCommand(
- 'touch /sdcard/host_heartbeat')
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ for d in devices:
+ d.RunShellCommand(['touch', '/sdcard/host_heartbeat'],
+ check_return=True)
except:
# Keep the heatbeat running bypassing all errors.
pass
diff --git a/build/android/java_cpp_enum.gypi b/build/android/java_cpp_enum.gypi
index b51351b..d4abafa 100644
--- a/build/android/java_cpp_enum.gypi
+++ b/build/android/java_cpp_enum.gypi
@@ -33,6 +33,11 @@
'generated_src_dirs': [
'<(output_dir)/',
],
+ # Ensure that the targets depending on this one are rebuilt if the sources
+ # of this one are modified.
+ 'additional_input_paths': [
+ '<(source_file)',
+ ],
},
},
'actions': [
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 5f00b31..ee52c71 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -19,9 +19,9 @@
import sys
import time
-from pylib import android_commands
from pylib import constants
from pylib import device_settings
+from pylib.device import battery_utils
from pylib.device import device_blacklist
from pylib.device import device_errors
from pylib.device import device_utils
@@ -41,54 +41,148 @@
HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP)
-def KillHostHeartbeat():
- ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
- stdout, _ = ps.communicate()
- matches = re.findall('\\n.*host_heartbeat.*', stdout)
- for match in matches:
- logging.info('An instance of host heart beart running... will kill')
- pid = re.findall(r'(\S+)', match)[1]
- subprocess.call(['kill', str(pid)])
+class _PHASES(object):
+ WIPE = 'wipe'
+ PROPERTIES = 'properties'
+ FINISH = 'finish'
+
+ ALL = [WIPE, PROPERTIES, FINISH]
-def LaunchHostHeartbeat():
- # Kill if existing host_heartbeat
- KillHostHeartbeat()
- # Launch a new host_heartbeat
- logging.info('Spawning host heartbeat...')
- subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
- 'build/android/host_heartbeat.py')])
+def ProvisionDevices(options):
+ if options.device is not None:
+ devices = [options.device]
+ else:
+ devices = device_utils.DeviceUtils.HealthyDevices()
+
+ parallel_devices = device_utils.DeviceUtils.parallel(devices)
+ parallel_devices.pMap(ProvisionDevice, options)
+ if options.auto_reconnect:
+ _LaunchHostHeartbeat()
+ blacklist = device_blacklist.ReadBlacklist()
+ if all(d in blacklist for d in devices):
+ raise device_errors.NoDevicesError
+ return 0
-def PushAndLaunchAdbReboot(device, target):
- """Pushes and launches the adb_reboot binary on the device.
+def ProvisionDevice(device, options):
+ if options.reboot_timeout:
+ reboot_timeout = options.reboot_timeout
+ elif (device.build_version_sdk >=
+ constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+ reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
+ else:
+ reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
+
+ def should_run_phase(phase_name):
+ return not options.phases or phase_name in options.phases
+
+ def run_phase(phase_func, reboot=True):
+ device.WaitUntilFullyBooted(timeout=reboot_timeout)
+ phase_func(device, options)
+ if reboot:
+ device.Reboot(False, retries=0)
+ device.adb.WaitForDevice()
+
+ try:
+ if should_run_phase(_PHASES.WIPE):
+ run_phase(WipeDevice)
+
+ if should_run_phase(_PHASES.PROPERTIES):
+ run_phase(SetProperties)
+
+ if should_run_phase(_PHASES.FINISH):
+ run_phase(FinishProvisioning, reboot=False)
+
+ except (errors.WaitForResponseTimedOutError,
+ device_errors.CommandTimeoutError):
+ logging.exception('Timed out waiting for device %s. Adding to blacklist.',
+ str(device))
+ device_blacklist.ExtendBlacklist([str(device)])
+
+ except device_errors.CommandFailedError:
+ logging.exception('Failed to provision device %s. Adding to blacklist.',
+ str(device))
+ device_blacklist.ExtendBlacklist([str(device)])
+
+
+def WipeDevice(device, options):
+ """Wipes data from device, keeping only the adb_keys for authorization.
+
+ After wiping data on a device that has been authorized, adb can still
+ communicate with the device, but after reboot the device will need to be
+ re-authorized because the adb keys file is stored in /data/misc/adb/.
+ Thus, adb_keys file is rewritten so the device does not need to be
+ re-authorized.
Arguments:
- device: The DeviceUtils instance for the device to which the adb_reboot
- binary should be pushed.
- target: The build target (example, Debug or Release) which helps in
- locating the adb_reboot binary.
+ device: the device to wipe
"""
- logging.info('Will push and launch adb_reboot on %s' % str(device))
- # Kill if adb_reboot is already running.
+ if options.skip_wipe:
+ return
+
try:
- # Don't try to kill adb_reboot more than once. We don't expect it to be
- # running at all.
- device.KillAll('adb_reboot', blocking=True, timeout=2, retries=0)
+ device.EnableRoot()
+ device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
+ if device_authorized:
+ adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
+ as_root=True).splitlines()
+ device.RunShellCommand(['wipe', 'data'],
+ as_root=True, check_return=True)
+ device.adb.WaitForDevice()
+
+ if device_authorized:
+ adb_keys_set = set(adb_keys)
+ for adb_key_file in options.adb_key_files or []:
+ try:
+ with open(adb_key_file, 'r') as f:
+ adb_public_keys = f.readlines()
+ adb_keys_set.update(adb_public_keys)
+ except IOError:
+ logging.warning('Unable to find adb keys file %s.' % adb_key_file)
+ _WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
except device_errors.CommandFailedError:
- # We can safely ignore the exception because we don't expect adb_reboot
- # to be running.
- pass
- # Push adb_reboot
- logging.info(' Pushing adb_reboot ...')
- adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
- 'out/%s/adb_reboot' % target)
- device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
- # Launch adb_reboot
- logging.info(' Launching adb_reboot ...')
- device.RunShellCommand([
- device.GetDevicePieWrapper(),
- '/data/local/tmp/adb_reboot'])
+ logging.exception('Possible failure while wiping the device. '
+ 'Attempting to continue.')
+
+
+def _WriteAdbKeysFile(device, adb_keys_string):
+ dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
+ device.RunShellCommand(['mkdir', '-p', dir_path],
+ as_root=True, check_return=True)
+ device.RunShellCommand(['restorecon', dir_path],
+ as_root=True, check_return=True)
+ device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
+ device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE],
+ as_root=True, check_return=True)
+
+
+def SetProperties(device, options):
+ try:
+ device.EnableRoot()
+ except device_errors.CommandFailedError as e:
+ logging.warning(str(e))
+
+ _ConfigureLocalProperties(device, options.enable_java_debug)
+ device_settings.ConfigureContentSettings(
+ device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
+ if options.disable_location:
+ device_settings.ConfigureContentSettings(
+ device, device_settings.DISABLE_LOCATION_SETTINGS)
+ else:
+ device_settings.ConfigureContentSettings(
+ device, device_settings.ENABLE_LOCATION_SETTINGS)
+ device_settings.SetLockScreenSettings(device)
+ if options.disable_network:
+ device_settings.ConfigureContentSettings(
+ device, device_settings.NETWORK_DISABLED_SETTINGS)
+
+ if options.min_battery_level is not None:
+ try:
+ battery = battery_utils.BatteryUtils(device)
+ battery.ChargeDeviceToLevel(options.min_battery_level)
+ except device_errors.CommandFailedError as e:
+ logging.exception('Unable to charge device to specified level.')
def _ConfigureLocalProperties(device, java_debug=True):
@@ -101,7 +195,8 @@
'ro.setupwizard.mode=DISABLED',
]
if java_debug:
- local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY)
+ local_props.append(
+ '%s=all' % device_utils.DeviceUtils.JAVA_ASSERT_PROPERTY)
local_props.append('debug.checkjni=1')
try:
device.WriteFile(
@@ -110,153 +205,66 @@
# Android will not respect the local props file if it is world writable.
device.RunShellCommand(
['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH],
- as_root=True)
- except device_errors.CommandFailedError as e:
- logging.warning(str(e))
-
- # LOCAL_PROPERTIES_PATH = '/data/local.prop'
-
-def WriteAdbKeysFile(device, adb_keys_string):
- dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
- device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True)
- device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
- device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
- device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
- as_root=True)
+ as_root=True, check_return=True)
+ except device_errors.CommandFailedError:
+ logging.exception('Failed to configure local properties.')
-def WipeDeviceData(device, options):
- """Wipes data from device, keeping only the adb_keys for authorization.
+def FinishProvisioning(device, options):
+ device.RunShellCommand(
+ ['date', '-s', time.strftime('%Y%m%d.%H%M%S', time.gmtime())],
+ as_root=True, check_return=True)
+ props = device.RunShellCommand('getprop', check_return=True)
+ for prop in props:
+ logging.info(' %s' % prop)
+ if options.auto_reconnect:
+ _PushAndLaunchAdbReboot(device, options.target)
- After wiping data on a device that has been authorized, adb can still
- communicate with the device, but after reboot the device will need to be
- re-authorized because the adb keys file is stored in /data/misc/adb/.
- Thus, adb_keys file is rewritten so the device does not need to be
- re-authorized.
+
+def _PushAndLaunchAdbReboot(device, target):
+ """Pushes and launches the adb_reboot binary on the device.
Arguments:
- device: the device to wipe
+ device: The DeviceUtils instance for the device to which the adb_reboot
+ binary should be pushed.
+ target: The build target (example, Debug or Release) which helps in
+ locating the adb_reboot binary.
"""
- device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
- if device_authorized:
- adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
- as_root=True).splitlines()
- device.RunShellCommand('wipe data', as_root=True)
- if device_authorized:
- adb_keys_set = set(adb_keys)
- for adb_key_file in options.adb_key_files or []:
- try:
- with open(adb_key_file, 'r') as f:
- adb_public_keys = f.readlines()
- adb_keys_set.update(adb_public_keys)
- except IOError:
- logging.warning('Unable to find adb keys file %s.' % adb_key_file)
- WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
+ logging.info('Will push and launch adb_reboot on %s' % str(device))
+ # Kill if adb_reboot is already running.
+ device.KillAll('adb_reboot', blocking=True, timeout=2, quiet=True)
+ # Push adb_reboot
+ logging.info(' Pushing adb_reboot ...')
+ adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
+ 'out/%s/adb_reboot' % target)
+ device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
+ # Launch adb_reboot
+ logging.info(' Launching adb_reboot ...')
+ device.RunShellCommand(
+ [device.GetDevicePieWrapper(), '/data/local/tmp/adb_reboot'],
+ check_return=True)
-def WipeDeviceIfPossible(device, timeout, options):
- try:
- device.EnableRoot()
- WipeDeviceData(device, options)
- device.Reboot(True, timeout=timeout, retries=0)
- except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError):
- pass
+def _LaunchHostHeartbeat():
+ # Kill if existing host_heartbeat
+ KillHostHeartbeat()
+ # Launch a new host_heartbeat
+ logging.info('Spawning host heartbeat...')
+ subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
+ 'build/android/host_heartbeat.py')])
-def ChargeDeviceToLevel(device, level):
- def device_charged():
- battery_level = device.GetBatteryInfo().get('level')
- if battery_level is None:
- logging.warning('Unable to find current battery level.')
- battery_level = 100
- else:
- logging.info('current battery level: %d', battery_level)
- battery_level = int(battery_level)
- return battery_level >= level
-
- timeout_retry.WaitFor(device_charged, wait_period=60)
-
-
-def ProvisionDevice(device, options):
- if options.reboot_timeout:
- reboot_timeout = options.reboot_timeout
- elif (device.build_version_sdk >=
- constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
- reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
- else:
- reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
-
- try:
- if not options.skip_wipe:
- WipeDeviceIfPossible(device, reboot_timeout, options)
- try:
- device.EnableRoot()
- except device_errors.CommandFailedError as e:
- logging.warning(str(e))
- _ConfigureLocalProperties(device, options.enable_java_debug)
- device_settings.ConfigureContentSettings(
- device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
- if options.disable_location:
- device_settings.ConfigureContentSettings(
- device, device_settings.DISABLE_LOCATION_SETTINGS)
- else:
- device_settings.ConfigureContentSettings(
- device, device_settings.ENABLE_LOCATION_SETTINGS)
- device_settings.SetLockScreenSettings(device)
- if options.disable_network:
- device_settings.ConfigureContentSettings(
- device, device_settings.NETWORK_DISABLED_SETTINGS)
- if options.min_battery_level is not None:
- try:
- device.SetCharging(True)
- ChargeDeviceToLevel(device, options.min_battery_level)
- except device_errors.CommandFailedError as e:
- logging.exception('Unable to charge device to specified level.')
-
- if not options.skip_wipe:
- device.Reboot(True, timeout=reboot_timeout, retries=0)
- device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S',
- time.gmtime()),
- as_root=True)
- props = device.RunShellCommand('getprop')
- for prop in props:
- logging.info(' %s' % prop)
- if options.auto_reconnect:
- PushAndLaunchAdbReboot(device, options.target)
- except (errors.WaitForResponseTimedOutError,
- device_errors.CommandTimeoutError):
- logging.info('Timed out waiting for device %s. Adding to blacklist.',
- str(device))
- # Device black list is reset by bb_device_status_check.py per build.
- device_blacklist.ExtendBlacklist([str(device)])
- except device_errors.CommandFailedError:
- logging.exception('Failed to provision device %s. Adding to blacklist.',
- str(device))
- device_blacklist.ExtendBlacklist([str(device)])
-
-
-def ProvisionDevices(options):
- if options.device is not None:
- devices = [options.device]
- else:
- devices = android_commands.GetAttachedDevices()
-
- parallel_devices = device_utils.DeviceUtils.parallel(devices)
- parallel_devices.pMap(ProvisionDevice, options)
- if options.auto_reconnect:
- LaunchHostHeartbeat()
- blacklist = device_blacklist.ReadBlacklist()
- if all(d in blacklist for d in devices):
- raise device_errors.NoDevicesError
- return 0
+def KillHostHeartbeat():
+ ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+ stdout, _ = ps.communicate()
+ matches = re.findall('\\n.*host_heartbeat.*', stdout)
+ for match in matches:
+ logging.info('An instance of host heart beart running... will kill')
+ pid = re.findall(r'(\S+)', match)[1]
+ subprocess.call(['kill', str(pid)])
def main():
- custom_handler = logging.StreamHandler(sys.stdout)
- custom_handler.setFormatter(run_tests_helper.CustomFormatter())
- logging.getLogger().addHandler(custom_handler)
- logging.getLogger().setLevel(logging.INFO)
-
# Recommended options on perf bots:
# --disable-network
# TODO(tonyg): We eventually want network on. However, currently radios
@@ -271,6 +279,10 @@
parser.add_argument('-d', '--device', metavar='SERIAL',
help='the serial number of the device to be provisioned'
' (the default is to provision all devices attached)')
+ parser.add_argument('--phase', action='append', choices=_PHASES.ALL,
+ dest='phases',
+ help='Phases of provisioning to run. '
+ '(If omitted, all phases will be run.)')
parser.add_argument('--skip-wipe', action='store_true', default=False,
help="don't wipe device data during provisioning")
parser.add_argument('--reboot-timeout', metavar='SECS', type=int,
@@ -294,9 +306,13 @@
' disconnections')
parser.add_argument('--adb-key-files', type=str, nargs='+',
help='list of adb keys to push to device')
+ parser.add_argument('-v', '--verbose', action='count', default=1,
+ help='Log more information.')
args = parser.parse_args()
constants.SetBuildType(args.target)
+ run_tests_helper.SetLogLevel(args.verbose)
+
return ProvisionDevices(args)
diff --git a/build/android/pylib/base/base_test_runner.py b/build/android/pylib/base/base_test_runner.py
index 4e2eae7..1ca0338 100644
--- a/build/android/pylib/base/base_test_runner.py
+++ b/build/android/pylib/base/base_test_runner.py
@@ -26,12 +26,11 @@
class BaseTestRunner(object):
"""Base class for running tests on a single device."""
- def __init__(self, device_serial, tool, cleanup_test_files=False):
+ def __init__(self, device_serial, tool):
"""
Args:
device: Tests will run on the device of this ID.
tool: Name of the Valgrind tool.
- cleanup_test_files: Whether or not to cleanup test files on device.
"""
self.device_serial = device_serial
self.device = device_utils.DeviceUtils(device_serial)
@@ -45,7 +44,6 @@
# starting it in TestServerThread.
self.test_server_spawner_port = 0
self.test_server_port = 0
- self._cleanup_test_files = cleanup_test_files
def _PushTestServerPortInfoToDevice(self):
"""Pushes the latest port information to device."""
@@ -77,8 +75,6 @@
def TearDown(self):
"""Run once after all tests are run."""
self.ShutdownHelperToolsForTestSuite()
- if self._cleanup_test_files:
- self.device.old_interface.RemovePushedFiles()
def LaunchTestHttpServer(self, document_root, port=None,
extra_config_contents=None):
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants/__init__.py
similarity index 95%
rename from build/android/pylib/constants.py
rename to build/android/pylib/constants/__init__.py
index 34dbf19..6e92f6d 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants/__init__.py
@@ -3,6 +3,9 @@
# found in the LICENSE file.
"""Defines a set of constants shared by test runners and other scripts."""
+
+# TODO(jbudorick): Split these constants into coherent modules.
+
# pylint: disable=W0212
import collections
@@ -13,7 +16,7 @@
DIR_SOURCE_ROOT = os.environ.get('CHECKOUT_SOURCE_ROOT',
os.path.abspath(os.path.join(os.path.dirname(__file__),
- os.pardir, os.pardir, os.pardir)))
+ os.pardir, os.pardir, os.pardir, os.pardir)))
ISOLATE_DEPS_DIR = os.path.join(DIR_SOURCE_ROOT, 'isolate_deps_dir')
CHROME_SHELL_HOST_DRIVEN_DIR = os.path.join(
@@ -50,7 +53,7 @@
'chrome_devtools_remote',
None),
'chrome_dev': PackageInfo(
- 'com.google.android.apps.chrome_dev',
+ 'com.chrome.dev',
'com.google.android.apps.chrome.Main',
'/data/local/chrome-command-line',
'chrome_devtools_remote',
@@ -103,6 +106,13 @@
'/data/local/tmp/chrome-native-tests-command-line',
None,
None),
+ 'components_browsertests': PackageInfo(
+ 'org.chromium.components_browsertests_apk',
+ ('org.chromium.components_browsertests_apk' +
+ '.ComponentsBrowserTestsActivity'),
+ '/data/local/tmp/components-browser-tests-command-line',
+ None,
+ None),
'content_browsertests': PackageInfo(
'org.chromium.content_browsertests_apk',
'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity',
diff --git a/build/android/pylib/constants/keyevent.py b/build/android/pylib/constants/keyevent.py
new file mode 100644
index 0000000..06736b3
--- /dev/null
+++ b/build/android/pylib/constants/keyevent.py
@@ -0,0 +1,14 @@
+# 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.
+
+"""Android KeyEvent constants.
+
+http://developer.android.com/reference/android/view/KeyEvent.html
+"""
+
+KEYCODE_BACK = 4
+KEYCODE_DPAD_RIGHT = 22
+KEYCODE_ENTER = 66
+KEYCODE_MENU = 82
+
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 36f8f48..20787c1 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,6 +12,7 @@
import errno
import logging
import os
+import re
from pylib import cmd_helper
from pylib import constants
@@ -23,6 +24,10 @@
_DEFAULT_TIMEOUT = 30
_DEFAULT_RETRIES = 2
+_EMULATOR_RE = re.compile(r'^emulator-[0-9]+$')
+
+_READY_STATE = 'device'
+
def _VerifyLocalFileExists(path):
"""Verifies a local file exists.
@@ -158,9 +163,15 @@
cls._RunAdbCmd(['start-server'], timeout=timeout, retries=retries,
cpu_affinity=0)
- # TODO(craigdh): Determine the filter criteria that should be supported.
@classmethod
def GetDevices(cls, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
+ """DEPRECATED. Refer to Devices(...) below."""
+ # TODO(jbudorick): Remove this function once no more clients are using it.
+ return cls.Devices(timeout=timeout, retries=retries)
+
+ @classmethod
+ def Devices(cls, is_ready=True, timeout=_DEFAULT_TIMEOUT,
+ retries=_DEFAULT_RETRIES):
"""Get the list of active attached devices.
Args:
@@ -171,9 +182,9 @@
AdbWrapper instances.
"""
output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries)
- lines = [line.split() for line in output.splitlines()]
+ lines = (line.split() for line in output.splitlines())
return [AdbWrapper(line[0]) for line in lines
- if len(line) == 2 and line[1] == 'device']
+ if len(line) == 2 and (not is_ready or line[1] == _READY_STATE)]
def GetDeviceSerial(self):
"""Gets the device serial number associated with this object.
@@ -530,3 +541,15 @@
if 'cannot' in output:
raise device_errors.AdbCommandFailedError(
['root'], output, device_serial=self._device_serial)
+
+ @property
+ def is_emulator(self):
+ return _EMULATOR_RE.match(self._device_serial)
+
+ @property
+ def is_ready(self):
+ try:
+ return self.GetState() == _READY_STATE
+ except device_errors.CommandFailedError:
+ return False
+
diff --git a/build/android/pylib/device/adb_wrapper_test.py b/build/android/pylib/device/adb_wrapper_test.py
index 52ba2e3..5fc9eb6 100644
--- a/build/android/pylib/device/adb_wrapper_test.py
+++ b/build/android/pylib/device/adb_wrapper_test.py
@@ -16,7 +16,7 @@
class TestAdbWrapper(unittest.TestCase):
def setUp(self):
- devices = adb_wrapper.AdbWrapper.GetDevices()
+ devices = adb_wrapper.AdbWrapper.Devices()
assert devices, 'A device must be attached'
self._adb = devices[0]
self._adb.WaitForDevice()
diff --git a/build/android/pylib/device/battery_utils.py b/build/android/pylib/device/battery_utils.py
new file mode 100644
index 0000000..cca2cf9
--- /dev/null
+++ b/build/android/pylib/device/battery_utils.py
@@ -0,0 +1,386 @@
+# 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.
+
+"""Provides a variety of device interactions with power.
+"""
+# pylint: disable=unused-argument
+
+import collections
+import contextlib
+import csv
+import logging
+
+from pylib import constants
+from pylib.device import decorators
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.utils import timeout_retry
+
+_DEFAULT_TIMEOUT = 30
+_DEFAULT_RETRIES = 3
+
+_CONTROL_CHARGING_COMMANDS = [
+ {
+ # Nexus 4
+ 'witness_file': '/sys/module/pm8921_charger/parameters/disabled',
+ 'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled',
+ 'disable_command':
+ 'echo 1 > /sys/module/pm8921_charger/parameters/disabled',
+ },
+ {
+ # Nexus 5
+ # Setting the HIZ bit of the bq24192 causes the charger to actually ignore
+ # energy coming from USB. Setting the power_supply offline just updates the
+ # Android system to reflect that.
+ 'witness_file': '/sys/kernel/debug/bq24192/INPUT_SRC_CONT',
+ 'enable_command': (
+ 'echo 0x4A > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+ 'echo 1 > /sys/class/power_supply/usb/online'),
+ 'disable_command': (
+ 'echo 0xCA > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+ 'chmod 644 /sys/class/power_supply/usb/online && '
+ 'echo 0 > /sys/class/power_supply/usb/online'),
+ },
+]
+
+# The list of useful dumpsys columns.
+# Index of the column containing the format version.
+_DUMP_VERSION_INDEX = 0
+# Index of the column containing the type of the row.
+_ROW_TYPE_INDEX = 3
+# Index of the column containing the uid.
+_PACKAGE_UID_INDEX = 4
+# Index of the column containing the application package.
+_PACKAGE_NAME_INDEX = 5
+# The column containing the uid of the power data.
+_PWI_UID_INDEX = 1
+# The column containing the type of consumption. Only consumtion since last
+# charge are of interest here.
+_PWI_AGGREGATION_INDEX = 2
+# The column containing the amount of power used, in mah.
+_PWI_POWER_CONSUMPTION_INDEX = 5
+
+
+class BatteryUtils(object):
+
+ def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
+ default_retries=_DEFAULT_RETRIES):
+ """BatteryUtils constructor.
+
+ Args:
+ device: A DeviceUtils instance.
+ default_timeout: An integer containing the default number of seconds to
+ wait for an operation to complete if no explicit value
+ is provided.
+ default_retries: An integer containing the default number or times an
+ operation should be retried on failure if no explicit
+ value is provided.
+
+ Raises:
+ TypeError: If it is not passed a DeviceUtils instance.
+ """
+ if not isinstance(device, device_utils.DeviceUtils):
+ raise TypeError('Must be initialized with DeviceUtils object.')
+ self._device = device
+ self._cache = device.GetClientCache(self.__class__.__name__)
+ self._default_timeout = default_timeout
+ self._default_retries = default_retries
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetNetworkData(self, package, timeout=None, retries=None):
+ """ Get network data for specific package.
+
+ Args:
+ package: package name you want network data for.
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Returns:
+ Tuple of (sent_data, recieved_data)
+ None if no network data found
+ """
+ # If device_utils clears cache, cache['uids'] doesn't exist
+ if 'uids' not in self._cache:
+ self._cache['uids'] = {}
+ if package not in self._cache['uids']:
+ self.GetPowerData()
+ if package not in self._cache['uids']:
+ logging.warning('No UID found for %s. Can\'t get network data.',
+ package)
+ return None
+
+ network_data_path = '/proc/uid_stat/%s/' % self._cache['uids'][package]
+ try:
+ send_data = int(self._device.ReadFile(network_data_path + 'tcp_snd'))
+ # If ReadFile throws exception, it means no network data usage file for
+ # package has been recorded. Return 0 sent and 0 received.
+ except device_errors.AdbShellCommandFailedError:
+ logging.warning('No sent data found for package %s', package)
+ send_data = 0
+ try:
+ recv_data = int(self._device.ReadFile(network_data_path + 'tcp_rcv'))
+ except device_errors.AdbShellCommandFailedError:
+ logging.warning('No received data found for package %s', package)
+ recv_data = 0
+ return (send_data, recv_data)
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetPowerData(self, timeout=None, retries=None):
+ """ Get power data for device.
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Returns:
+ Dict of power data, keyed on package names.
+ {
+ package_name: {
+ 'uid': uid,
+ 'data': [1,2,3]
+ },
+ }
+ """
+ if 'uids' not in self._cache:
+ self._cache['uids'] = {}
+ dumpsys_output = self._device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True)
+ csvreader = csv.reader(dumpsys_output)
+ pwi_entries = collections.defaultdict(list)
+ for entry in csvreader:
+ if entry[_DUMP_VERSION_INDEX] not in ['8', '9']:
+ # Wrong dumpsys version.
+ raise device_errors.DeviceVersionError(
+ 'Dumpsys version must be 8 or 9. %s found.'
+ % entry[_DUMP_VERSION_INDEX])
+ if _ROW_TYPE_INDEX < len(entry) and entry[_ROW_TYPE_INDEX] == 'uid':
+ current_package = entry[_PACKAGE_NAME_INDEX]
+ if (self._cache['uids'].get(current_package)
+ and self._cache['uids'].get(current_package)
+ != entry[_PACKAGE_UID_INDEX]):
+ raise device_errors.CommandFailedError(
+ 'Package %s found multiple times with differnt UIDs %s and %s'
+ % (current_package, self._cache['uids'][current_package],
+ entry[_PACKAGE_UID_INDEX]))
+ self._cache['uids'][current_package] = entry[_PACKAGE_UID_INDEX]
+ elif (_PWI_POWER_CONSUMPTION_INDEX < len(entry)
+ and entry[_ROW_TYPE_INDEX] == 'pwi'
+ and entry[_PWI_AGGREGATION_INDEX] == 'l'):
+ pwi_entries[entry[_PWI_UID_INDEX]].append(
+ float(entry[_PWI_POWER_CONSUMPTION_INDEX]))
+
+ return {p: {'uid': uid, 'data': pwi_entries[uid]}
+ for p, uid in self._cache['uids'].iteritems()}
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetPackagePowerData(self, package, timeout=None, retries=None):
+ """ Get power data for particular package.
+
+ Args:
+ package: Package to get power data on.
+
+ returns:
+ Dict of UID and power data.
+ {
+ 'uid': uid,
+ 'data': [1,2,3]
+ }
+ None if the package is not found in the power data.
+ """
+ return self.GetPowerData().get(package)
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetBatteryInfo(self, timeout=None, retries=None):
+ """Gets battery info for the device.
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+ Returns:
+ A dict containing various battery information as reported by dumpsys
+ battery.
+ """
+ result = {}
+ # Skip the first line, which is just a header.
+ for line in self._device.RunShellCommand(
+ ['dumpsys', 'battery'], check_return=True)[1:]:
+ # If usb charging has been disabled, an extra line of header exists.
+ if 'UPDATES STOPPED' in line:
+ logging.warning('Dumpsys battery not receiving updates. '
+ 'Run dumpsys battery reset if this is in error.')
+ elif ':' not in line:
+ logging.warning('Unknown line found in dumpsys battery: "%s"', line)
+ else:
+ k, v = line.split(':', 1)
+ result[k.strip()] = v.strip()
+ return result
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetCharging(self, timeout=None, retries=None):
+ """Gets the charging state of the device.
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+ Returns:
+ True if the device is charging, false otherwise.
+ """
+ battery_info = self.GetBatteryInfo()
+ for k in ('AC powered', 'USB powered', 'Wireless powered'):
+ if (k in battery_info and
+ battery_info[k].lower() in ('true', '1', 'yes')):
+ return True
+ return False
+
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def SetCharging(self, enabled, timeout=None, retries=None):
+ """Enables or disables charging on the device.
+
+ Args:
+ enabled: A boolean indicating whether charging should be enabled or
+ disabled.
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Raises:
+ device_errors.CommandFailedError: If method of disabling charging cannot
+ be determined.
+ """
+ if 'charging_config' not in self._cache:
+ for c in _CONTROL_CHARGING_COMMANDS:
+ if self._device.FileExists(c['witness_file']):
+ self._cache['charging_config'] = c
+ break
+ else:
+ raise device_errors.CommandFailedError(
+ 'Unable to find charging commands.')
+
+ if enabled:
+ command = self._cache['charging_config']['enable_command']
+ else:
+ command = self._cache['charging_config']['disable_command']
+
+ def set_and_verify_charging():
+ self._device.RunShellCommand(command, check_return=True)
+ return self.GetCharging() == enabled
+
+ timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
+
+ # TODO(rnephew): Make private when all use cases can use the context manager.
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def DisableBatteryUpdates(self, timeout=None, retries=None):
+ """ Resets battery data and makes device appear like it is not
+ charging so that it will collect power data since last charge.
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Raises:
+ device_errors.CommandFailedError: When resetting batterystats fails to
+ reset power values.
+ device_errors.DeviceVersionError: If device is not L or higher.
+ """
+ def battery_updates_disabled():
+ return self.GetCharging() is False
+
+ if (self._device.build_version_sdk <
+ constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+ raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+ self._device.RunShellCommand(
+ ['dumpsys', 'battery', 'reset'], check_return=True)
+ self._device.RunShellCommand(
+ ['dumpsys', 'batterystats', '--reset'], check_return=True)
+ battery_data = self._device.RunShellCommand(
+ ['dumpsys', 'batterystats', '--charged', '--checkin'],
+ check_return=True)
+ ROW_TYPE_INDEX = 3
+ PWI_POWER_INDEX = 5
+ for line in battery_data:
+ l = line.split(',')
+ if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
+ and l[PWI_POWER_INDEX] != 0):
+ raise device_errors.CommandFailedError(
+ 'Non-zero pmi value found after reset.')
+ self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'],
+ check_return=True)
+ self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
+ check_return=True)
+ timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
+
+ # TODO(rnephew): Make private when all use cases can use the context manager.
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def EnableBatteryUpdates(self, timeout=None, retries=None):
+ """ Restarts device charging so that dumpsys no longer collects power data.
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Raises:
+ device_errors.DeviceVersionError: If device is not L or higher.
+ """
+ def battery_updates_enabled():
+ return self.GetCharging() is True
+
+ if (self._device.build_version_sdk <
+ constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+ raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+ self._device.RunShellCommand(['dumpsys', 'battery', 'reset'],
+ check_return=True)
+ timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
+
+ @contextlib.contextmanager
+ def BatteryMeasurement(self, timeout=None, retries=None):
+ """Context manager that enables battery data collection. It makes
+ the device appear to stop charging so that dumpsys will start collecting
+ power data since last charge. Once the with block is exited, charging is
+ resumed and power data since last charge is no longer collected.
+
+ Only for devices L and higher.
+
+ Example usage:
+ with BatteryMeasurement():
+ browser_actions()
+ get_power_data() # report usage within this block
+ after_measurements() # Anything that runs after power
+ # measurements are collected
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Raises:
+ device_errors.DeviceVersionError: If device is not L or higher.
+ """
+ if (self._device.build_version_sdk <
+ constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+ raise device_errors.DeviceVersionError('Device must be L or higher.')
+ try:
+ self.DisableBatteryUpdates(timeout=timeout, retries=retries)
+ yield
+ finally:
+ self.EnableBatteryUpdates(timeout=timeout, retries=retries)
+
+ def ChargeDeviceToLevel(self, level, wait_period=60):
+ """Enables charging and waits for device to be charged to given level.
+
+ Args:
+ level: level of charge to wait for.
+ wait_period: time in seconds to wait between checking.
+ """
+ self.SetCharging(True)
+
+ def device_charged():
+ battery_level = self.GetBatteryInfo().get('level')
+ if battery_level is None:
+ logging.warning('Unable to find current battery level.')
+ battery_level = 100
+ else:
+ logging.info('current battery level: %s', battery_level)
+ battery_level = int(battery_level)
+ return battery_level >= level
+
+ timeout_retry.WaitFor(device_charged, wait_period=wait_period)
diff --git a/build/android/pylib/device/battery_utils_test.py b/build/android/pylib/device/battery_utils_test.py
new file mode 100755
index 0000000..15b4c34
--- /dev/null
+++ b/build/android/pylib/device/battery_utils_test.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+# 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.
+
+"""
+Unit tests for the contents of battery_utils.py
+"""
+
+# pylint: disable=W0613
+
+import logging
+import os
+import sys
+import unittest
+
+from pylib import android_commands
+from pylib import constants
+from pylib.device import battery_utils
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.device import device_utils_test
+from pylib.utils import mock_calls
+
+# RunCommand from third_party/android_testrunner/run_command.py is mocked
+# below, so its path needs to be in sys.path.
+sys.path.append(os.path.join(
+ constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner'))
+
+sys.path.append(os.path.join(
+ constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock # pylint: disable=F0401
+
+_DUMPSYS_OUTPUT = [
+ '9,0,i,uid,1000,test_package1',
+ '9,0,i,uid,1001,test_package2',
+ '9,1000,l,pwi,uid,1',
+ '9,1001,l,pwi,uid,2'
+]
+
+
+class BatteryUtilsTest(mock_calls.TestCase):
+
+ def ShellError(self, output=None, status=1):
+ def action(cmd, *args, **kwargs):
+ raise device_errors.AdbShellCommandFailedError(
+ cmd, output, status, str(self.device))
+ if output is None:
+ output = 'Permission denied\n'
+ return action
+
+ def setUp(self):
+ self.adb = device_utils_test._AdbWrapperMock('0123456789abcdef')
+ self.device = device_utils.DeviceUtils(
+ self.adb, default_timeout=10, default_retries=0)
+ self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial'])
+ self.battery = battery_utils.BatteryUtils(
+ self.device, default_timeout=10, default_retries=0)
+
+
+class BatteryUtilsInitTest(unittest.TestCase):
+
+ def testInitWithDeviceUtil(self):
+ serial = '0fedcba987654321'
+ a = android_commands.AndroidCommands(device=serial)
+ d = device_utils.DeviceUtils(a)
+ b = battery_utils.BatteryUtils(d)
+ self.assertEqual(d, b._device)
+
+ def testInitWithMissing_fails(self):
+ with self.assertRaises(TypeError):
+ battery_utils.BatteryUtils(None)
+ with self.assertRaises(TypeError):
+ battery_utils.BatteryUtils('')
+
+
+class BatteryUtilsSetChargingTest(BatteryUtilsTest):
+
+ @mock.patch('time.sleep', mock.Mock())
+ def testSetCharging_enabled(self):
+ with self.assertCalls(
+ (self.call.device.FileExists(mock.ANY), True),
+ (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+ (self.call.battery.GetCharging(), False),
+ (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+ (self.call.battery.GetCharging(), True)):
+ self.battery.SetCharging(True)
+
+ def testSetCharging_alreadyEnabled(self):
+ with self.assertCalls(
+ (self.call.device.FileExists(mock.ANY), True),
+ (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+ (self.call.battery.GetCharging(), True)):
+ self.battery.SetCharging(True)
+
+ @mock.patch('time.sleep', mock.Mock())
+ def testSetCharging_disabled(self):
+ with self.assertCalls(
+ (self.call.device.FileExists(mock.ANY), True),
+ (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+ (self.call.battery.GetCharging(), True),
+ (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+ (self.call.battery.GetCharging(), False)):
+ self.battery.SetCharging(False)
+
+
+class BatteryUtilsSetBatteryMeasurementTest(BatteryUtilsTest):
+
+ def testBatteryMeasurement(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ mock.ANY, retries=0, single_line=True,
+ timeout=10, check_return=True), '22'),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'battery', 'reset'], check_return=True), []),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '--charged', '--checkin'],
+ check_return=True), []),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
+ (self.call.battery.GetCharging(), False),
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'battery', 'reset'], check_return=True), []),
+ (self.call.battery.GetCharging(), True)):
+ with self.battery.BatteryMeasurement():
+ pass
+
+
+class BatteryUtilsGetPowerData(BatteryUtilsTest):
+
+ def testGetPowerData(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT)):
+ data = self.battery.GetPowerData()
+ check = {
+ 'test_package1': {'uid': '1000', 'data': [1.0]},
+ 'test_package2': {'uid': '1001', 'data': [2.0]}
+ }
+ self.assertEqual(data, check)
+
+ def testGetPowerData_packageCollisionSame(self):
+ self.battery._cache['uids'] = {'test_package1': '1000'}
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT):
+ data = self.battery.GetPowerData()
+ check = {
+ 'test_package1': {'uid': '1000', 'data': [1.0]},
+ 'test_package2': {'uid': '1001', 'data': [2.0]}
+ }
+ self.assertEqual(data, check)
+
+ def testGetPowerData_packageCollisionDifferent(self):
+ self.battery._cache['uids'] = {'test_package1': '1'}
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT):
+ with self.assertRaises(device_errors.CommandFailedError):
+ self.battery.GetPowerData()
+
+ def testGetPowerData_cacheCleared(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT)):
+ self.battery._cache.clear()
+ data = self.battery.GetPowerData()
+ check = {
+ 'test_package1': {'uid': '1000', 'data': [1.0]},
+ 'test_package2': {'uid': '1001', 'data': [2.0]}
+ }
+ self.assertEqual(data, check)
+
+ def testGetPackagePowerData(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT)):
+ data = self.battery.GetPackagePowerData('test_package2')
+ self.assertEqual(data, {'uid': '1001', 'data': [2.0]})
+
+ def testGetPackagePowerData_badPackage(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT)):
+ data = self.battery.GetPackagePowerData('not_a_package')
+ self.assertEqual(data, None)
+
+
+class BatteryUtilsChargeDevice(BatteryUtilsTest):
+
+ @mock.patch('time.sleep', mock.Mock())
+ def testChargeDeviceToLevel(self):
+ with self.assertCalls(
+ (self.call.battery.SetCharging(True)),
+ (self.call.battery.GetBatteryInfo(), {'level': '50'}),
+ (self.call.battery.GetBatteryInfo(), {'level': '100'})):
+ self.battery.ChargeDeviceToLevel(95)
+
+
+class DeviceUtilsGetBatteryInfoTest(BatteryUtilsTest):
+
+ def testGetBatteryInfo_normal(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ ['dumpsys', 'battery'], check_return=True),
+ [
+ 'Current Battery Service state:',
+ ' AC powered: false',
+ ' USB powered: true',
+ ' level: 100',
+ ' temperature: 321',
+ ]):
+ self.assertEquals(
+ {
+ 'AC powered': 'false',
+ 'USB powered': 'true',
+ 'level': '100',
+ 'temperature': '321',
+ },
+ self.battery.GetBatteryInfo())
+
+ def testGetBatteryInfo_nothing(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ ['dumpsys', 'battery'], check_return=True), []):
+ self.assertEquals({}, self.battery.GetBatteryInfo())
+
+
+class DeviceUtilsGetChargingTest(BatteryUtilsTest):
+
+ def testGetCharging_usb(self):
+ with self.assertCall(
+ self.call.battery.GetBatteryInfo(), {'USB powered': 'true'}):
+ self.assertTrue(self.battery.GetCharging())
+
+ def testGetCharging_usbFalse(self):
+ with self.assertCall(
+ self.call.battery.GetBatteryInfo(), {'USB powered': 'false'}):
+ self.assertFalse(self.battery.GetCharging())
+
+ def testGetCharging_ac(self):
+ with self.assertCall(
+ self.call.battery.GetBatteryInfo(), {'AC powered': 'true'}):
+ self.assertTrue(self.battery.GetCharging())
+
+ def testGetCharging_wireless(self):
+ with self.assertCall(
+ self.call.battery.GetBatteryInfo(), {'Wireless powered': 'true'}):
+ self.assertTrue(self.battery.GetCharging())
+
+ def testGetCharging_unknown(self):
+ with self.assertCall(
+ self.call.battery.GetBatteryInfo(), {'level': '42'}):
+ self.assertFalse(self.battery.GetCharging())
+
+
+class DeviceUtilsGetNetworkDataTest(BatteryUtilsTest):
+
+ def testGetNetworkData_noDataUsage(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'),
+ self.ShellError()),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'),
+ self.ShellError())):
+ self.assertEquals(self.battery.GetNetworkData('test_package1'), (0, 0))
+
+ def testGetNetworkData_badPackage(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT):
+ self.assertEqual(self.battery.GetNetworkData('asdf'), None)
+
+ def testGetNetworkData_packageNotCached(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+ self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+ def testGetNetworkData_packageCached(self):
+ self.battery._cache['uids'] = {'test_package1': '1000'}
+ with self.assertCalls(
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+ self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+ def testGetNetworkData_clearedCache(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['dumpsys', 'batterystats', '-c'], check_return=True),
+ _DUMPSYS_OUTPUT),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+ (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+ self.battery._cache.clear()
+ self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+
+if __name__ == '__main__':
+ logging.getLogger().setLevel(logging.DEBUG)
+ unittest.main(verbosity=2)
diff --git a/build/android/pylib/device/decorators.py b/build/android/pylib/device/decorators.py
index 074a0fc..73c13da 100644
--- a/build/android/pylib/device/decorators.py
+++ b/build/android/pylib/device/decorators.py
@@ -11,6 +11,7 @@
import sys
import threading
+from pylib import cmd_helper
from pylib import constants
from pylib.device import device_errors
from pylib.utils import reraiser_thread
@@ -56,13 +57,16 @@
return timeout_retry.Run(impl, timeout, retries)
except old_errors.WaitForResponseTimedOutError as e:
raise device_errors.CommandTimeoutError(str(e)), None, (
- sys.exc_info()[2])
+ sys.exc_info()[2])
except old_errors.DeviceUnresponsiveError as e:
raise device_errors.DeviceUnreachableError(str(e)), None, (
- sys.exc_info()[2])
+ sys.exc_info()[2])
except reraiser_thread.TimeoutError as e:
raise device_errors.CommandTimeoutError(str(e)), None, (
- sys.exc_info()[2])
+ sys.exc_info()[2])
+ except cmd_helper.TimeoutError as e:
+ raise device_errors.CommandTimeoutError(str(e)), None, (
+ sys.exc_info()[2])
return TimeoutRetryWrapper
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py
index 26d9eaf..e94968f 100644
--- a/build/android/pylib/device/device_errors.py
+++ b/build/android/pylib/device/device_errors.py
@@ -42,6 +42,13 @@
super(AdbCommandFailedError, self).__init__(message, device_serial)
+class DeviceVersionError(CommandFailedError):
+ """Exception for device version failures."""
+
+ def __init__(self, message, device_serial=None):
+ super(DeviceVersionError, self).__init__(message, device_serial)
+
+
class AdbShellCommandFailedError(AdbCommandFailedError):
"""Exception for shell command failures run via adb."""
@@ -52,7 +59,11 @@
message.append(' exit status: %s\n' % status)
if output:
message.append(' output:\n')
- message.extend(' - %s\n' % line for line in output.splitlines())
+ if isinstance(output, basestring):
+ output_lines = output.splitlines()
+ else:
+ output_lines = output
+ message.extend(' - %s\n' % line for line in output_lines)
else:
message.append(" output: ''\n")
message = ''.join(message)
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 9f538e1..46aec6f 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -25,8 +25,10 @@
import pylib.android_commands
from pylib import cmd_helper
from pylib import constants
+from pylib import device_signal
from pylib.device import adb_wrapper
from pylib.device import decorators
+from pylib.device import device_blacklist
from pylib.device import device_errors
from pylib.device import intent
from pylib.device import logcat_monitor
@@ -72,6 +74,7 @@
},
]
+
@decorators.WithExplicitTimeoutAndRetries(
_DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
def GetAVDs():
@@ -168,6 +171,7 @@
self._default_timeout = default_timeout
self._default_retries = default_retries
self._cache = {}
+ self._client_caches = {}
assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
@@ -406,7 +410,7 @@
return not self.IsOnline()
self.adb.Reboot()
- self._cache = {}
+ self._ClearCache()
timeout_retry.WaitFor(device_offline, wait_period=1)
if block:
self.WaitUntilFullyBooted(wifi=wifi)
@@ -446,8 +450,8 @@
@decorators.WithTimeoutAndRetriesFromInstance()
def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
- as_root=False, single_line=False, timeout=None,
- retries=None):
+ as_root=False, single_line=False, large_output=False,
+ timeout=None, retries=None):
"""Run an ADB shell command.
The command to run |cmd| should be a sequence of program arguments or else
@@ -480,6 +484,8 @@
with root privileges.
single_line: A boolean indicating if only a single line of output is
expected.
+ large_output: Uses a work-around for large shell command output. Without
+ this large output will be truncated.
timeout: timeout in seconds
retries: number of retries
@@ -502,15 +508,49 @@
# using double quotes here to allow interpolation of shell variables
return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
- def do_run(cmd):
+ def run(cmd):
+ return self.adb.Shell(cmd)
+
+ def handle_check_return(cmd):
try:
- return self.adb.Shell(cmd)
+ return run(cmd)
except device_errors.AdbCommandFailedError as exc:
if check_return:
raise
else:
return exc.output
+ def handle_large_command(cmd):
+ if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
+ return handle_check_return(cmd)
+ else:
+ with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
+ self._WriteFileWithPush(script.name, cmd)
+ logging.info('Large shell command will be run from file: %s ...',
+ cmd[:100])
+ return handle_check_return('sh %s' % script.name_quoted)
+
+ def handle_large_output(cmd, large_output_mode):
+ if large_output_mode:
+ with device_temp_file.DeviceTempFile(self.adb) as large_output_file:
+ cmd = '%s > %s' % (cmd, large_output_file.name)
+ logging.info('Large output mode enabled. Will write output to device '
+ ' and read results from file.')
+ handle_large_command(cmd)
+ return self.ReadFile(large_output_file.name)
+ else:
+ try:
+ return handle_large_command(cmd)
+ except device_errors.AdbCommandFailedError as exc:
+ if exc.status is None:
+ logging.exception('No output found for %s', cmd)
+ logging.warning('Attempting to run in large_output mode.')
+ logging.warning('Use RunShellCommand(..., large_output=True) for '
+ 'shell commands that expect a lot of output.')
+ return handle_large_output(cmd, True)
+ else:
+ raise
+
if not isinstance(cmd, basestring):
cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
if env:
@@ -521,19 +561,9 @@
if as_root and self.NeedsSU():
# "su -c sh -c" allows using shell features in |cmd|
cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
- if timeout is None:
- timeout = self._default_timeout
- if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
- output = do_run(cmd)
- else:
- with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
- self._WriteFileWithPush(script.name, cmd)
- logging.info('Large shell command will be run from file: %s ...',
- cmd[:100])
- output = do_run('sh %s' % script.name_quoted)
+ output = handle_large_output(cmd, large_output).splitlines()
- output = output.splitlines()
if single_line:
if not output:
return ''
@@ -545,38 +575,70 @@
else:
return output
+ def _RunPipedShellCommand(self, script, **kwargs):
+ PIPESTATUS_LEADER = 'PIPESTATUS: '
+
+ script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER
+ kwargs['check_return'] = True
+ output = self.RunShellCommand(script, **kwargs)
+ pipestatus_line = output[-1]
+
+ if not pipestatus_line.startswith(PIPESTATUS_LEADER):
+ logging.error('Pipe exit statuses of shell script missing.')
+ raise device_errors.AdbShellCommandFailedError(
+ script, output, status=None,
+ device_serial=self.adb.GetDeviceSerial())
+
+ output = output[:-1]
+ statuses = [
+ int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()]
+ if any(statuses):
+ raise device_errors.AdbShellCommandFailedError(
+ script, output, status=statuses,
+ device_serial=self.adb.GetDeviceSerial())
+ return output
+
@decorators.WithTimeoutAndRetriesFromInstance()
- def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
- timeout=None, retries=None):
+ def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False,
+ blocking=False, quiet=False, timeout=None, retries=None):
"""Kill all processes with the given name on the device.
Args:
process_name: A string containing the name of the process to kill.
signum: An integer containing the signal number to send to kill. Defaults
- to 9 (SIGKILL).
+ to SIGKILL (9).
as_root: A boolean indicating whether the kill should be executed with
root privileges.
blocking: A boolean indicating whether we should wait until all processes
with the given |process_name| are dead.
+ quiet: A boolean indicating whether to ignore the fact that no processes
+ to kill were found.
timeout: timeout in seconds
retries: number of retries
+ Returns:
+ The number of processes attempted to kill.
+
Raises:
- CommandFailedError if no process was killed.
+ CommandFailedError if no process was killed and |quiet| is False.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- pids = self._GetPidsImpl(process_name)
+ pids = self.GetPids(process_name)
if not pids:
- raise device_errors.CommandFailedError(
- 'No process "%s"' % process_name, str(self))
+ if quiet:
+ return 0
+ else:
+ raise device_errors.CommandFailedError(
+ 'No process "%s"' % process_name, str(self))
cmd = ['kill', '-%d' % signum] + pids.values()
self.RunShellCommand(cmd, as_root=as_root, check_return=True)
if blocking:
+ # TODO(perezu): use timeout_retry.WaitFor
wait_period = 0.1
- while self._GetPidsImpl(process_name):
+ while self.GetPids(process_name):
time.sleep(wait_period)
return len(pids)
@@ -791,29 +853,27 @@
if not real_device_path:
return [(host_path, device_path)]
- host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path])
+ host_checksums = md5sum.CalculateHostMd5Sums([real_host_path])
device_paths_to_md5 = (
real_device_path if os.path.isfile(real_host_path)
else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path))
- for _, p in host_hash_tuples))
- device_hash_tuples = md5sum.CalculateDeviceMd5Sums(
+ for p in host_checksums.iterkeys()))
+ device_checksums = md5sum.CalculateDeviceMd5Sums(
device_paths_to_md5, self)
if os.path.isfile(host_path):
- if (not device_hash_tuples
- or device_hash_tuples[0].hash != host_hash_tuples[0].hash):
+ host_checksum = host_checksums.get(real_host_path)
+ device_checksum = device_checksums.get(real_device_path)
+ if host_checksum != device_checksum:
return [(host_path, device_path)]
else:
return []
else:
- device_tuple_dict = dict((d.path, d.hash) for d in device_hash_tuples)
to_push = []
- for host_hash, host_abs_path in (
- (h.hash, h.path) for h in host_hash_tuples):
+ for host_abs_path, host_checksum in host_checksums.iteritems():
device_abs_path = '%s/%s' % (
real_device_path, os.path.relpath(host_abs_path, real_host_path))
- if (device_abs_path not in device_tuple_dict
- or device_tuple_dict[device_abs_path] != host_hash):
+ if (device_checksums.get(device_abs_path) != host_checksum):
to_push.append((host_abs_path, device_abs_path))
return to_push
@@ -991,7 +1051,7 @@
else:
logging.warning('Could not determine size of %s.', device_path)
- if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH:
+ if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH:
return _JoinLines(self.RunShellCommand(
['cat', device_path], as_root=as_root, check_return=True))
elif as_root and self.NeedsSU():
@@ -1326,11 +1386,19 @@
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- return self._GetPidsImpl(process_name)
-
- def _GetPidsImpl(self, process_name):
procs_pids = {}
- for line in self.RunShellCommand('ps', check_return=True):
+ try:
+ ps_output = self._RunPipedShellCommand(
+ 'ps | grep -F %s' % cmd_helper.SingleQuote(process_name))
+ except device_errors.AdbShellCommandFailedError as e:
+ if e.status and isinstance(e.status, list) and not e.status[0]:
+ # If ps succeeded but grep failed, there were no processes with the
+ # given name.
+ return procs_pids
+ else:
+ raise
+
+ for line in ps_output:
try:
ps_data = line.split()
if process_name in ps_data[-1]:
@@ -1402,10 +1470,8 @@
'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean',
'Private_Dirty')
- showmap_out = self.RunShellCommand(
- ['showmap', str(pid)], as_root=True, check_return=True)
- if not showmap_out:
- raise device_errors.CommandFailedError('No output from showmap')
+ showmap_out = self._RunPipedShellCommand(
+ 'showmap %d | grep TOTAL' % int(pid), as_root=True)
split_totals = showmap_out[-1].split()
if (not split_totals
@@ -1439,155 +1505,6 @@
return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs)
@decorators.WithTimeoutAndRetriesFromInstance()
- def GetBatteryInfo(self, timeout=None, retries=None):
- """Gets battery info for the device.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
- Returns:
- A dict containing various battery information as reported by dumpsys
- battery.
- """
- result = {}
- # Skip the first line, which is just a header.
- for line in self.RunShellCommand(
- ['dumpsys', 'battery'], check_return=True)[1:]:
- # If usb charging has been disabled, an extra line of header exists.
- if 'UPDATES STOPPED' in line:
- logging.warning('Dumpsys battery not receiving updates. '
- 'Run dumpsys battery reset if this is in error.')
- elif ':' not in line:
- logging.warning('Unknown line found in dumpsys battery.')
- logging.warning(line)
- else:
- k, v = line.split(': ', 1)
- result[k.strip()] = v.strip()
- return result
-
- @decorators.WithTimeoutAndRetriesFromInstance()
- def GetCharging(self, timeout=None, retries=None):
- """Gets the charging state of the device.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
- Returns:
- True if the device is charging, false otherwise.
- """
- battery_info = self.GetBatteryInfo()
- for k in ('AC powered', 'USB powered', 'Wireless powered'):
- if (k in battery_info and
- battery_info[k].lower() in ('true', '1', 'yes')):
- return True
- return False
-
- @decorators.WithTimeoutAndRetriesFromInstance()
- def SetCharging(self, enabled, timeout=None, retries=None):
- """Enables or disables charging on the device.
-
- Args:
- enabled: A boolean indicating whether charging should be enabled or
- disabled.
- timeout: timeout in seconds
- retries: number of retries
- """
- if 'charging_config' not in self._cache:
- for c in _CONTROL_CHARGING_COMMANDS:
- if self.FileExists(c['witness_file']):
- self._cache['charging_config'] = c
- break
- else:
- raise device_errors.CommandFailedError(
- 'Unable to find charging commands.')
-
- if enabled:
- command = self._cache['charging_config']['enable_command']
- else:
- command = self._cache['charging_config']['disable_command']
-
- def set_and_verify_charging():
- self.RunShellCommand(command, check_return=True)
- return self.GetCharging() == enabled
-
- timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
-
- # TODO(rnephew): Make private when all use cases can use the context manager.
- @decorators.WithTimeoutAndRetriesFromInstance()
- def DisableBatteryUpdates(self, timeout=None, retries=None):
- """ Resets battery data and makes device appear like it is not
- charging so that it will collect power data since last charge.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
- """
- def battery_updates_disabled():
- return self.GetCharging() is False
-
- self.RunShellCommand(
- ['dumpsys', 'batterystats', '--reset'], check_return=True)
- battery_data = self.RunShellCommand(
- ['dumpsys', 'batterystats', '--charged', '--checkin'],
- check_return=True)
- ROW_TYPE_INDEX = 3
- PWI_POWER_INDEX = 5
- for line in battery_data:
- l = line.split(',')
- if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
- and l[PWI_POWER_INDEX] != 0):
- raise device_errors.CommandFailedError(
- 'Non-zero pmi value found after reset.')
- self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
- check_return=True)
- timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
-
- # TODO(rnephew): Make private when all use cases can use the context manager.
- @decorators.WithTimeoutAndRetriesFromInstance()
- def EnableBatteryUpdates(self, timeout=None, retries=None):
- """ Restarts device charging so that dumpsys no longer collects power data.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
- """
- def battery_updates_enabled():
- return self.GetCharging() is True
-
- self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'],
- check_return=True)
- self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True)
- timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
-
- @contextlib.contextmanager
- def BatteryMeasurement(self, timeout=None, retries=None):
- """Context manager that enables battery data collection. It makes
- the device appear to stop charging so that dumpsys will start collecting
- power data since last charge. Once the with block is exited, charging is
- resumed and power data since last charge is no longer collected.
-
- Only for devices L and higher.
-
- Example usage:
- with BatteryMeasurement():
- browser_actions()
- get_power_data() # report usage within this block
- after_measurements() # Anything that runs after power
- # measurements are collected
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
- """
- if self.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP:
- raise device_errors.CommandFailedError('Device must be L or higher.')
- try:
- self.DisableBatteryUpdates(timeout=timeout, retries=retries)
- yield
- finally:
- self.EnableBatteryUpdates(timeout=timeout, retries=retries)
-
- @decorators.WithTimeoutAndRetriesFromInstance()
def GetDevicePieWrapper(self, timeout=None, retries=None):
"""Gets the absolute path to the run_pie wrapper on the device.
@@ -1622,12 +1539,24 @@
return self._cache['run_pie']
+ def GetClientCache(self, client_name):
+ """Returns client cache."""
+ if client_name not in self._client_caches:
+ self._client_caches[client_name] = {}
+ return self._client_caches[client_name]
+
+ def _ClearCache(self):
+ """Clears all caches."""
+ for client in self._client_caches:
+ self._client_caches[client].clear()
+ self._cache.clear()
+
@classmethod
def parallel(cls, devices=None, async=False):
"""Creates a Parallelizer to operate over the provided list of devices.
If |devices| is either |None| or an empty list, the Parallelizer will
- operate over all attached devices.
+ operate over all attached devices that have not been blacklisted.
Args:
devices: A list of either DeviceUtils instances or objects from
@@ -1640,11 +1569,25 @@
A Parallelizer operating over |devices|.
"""
if not devices:
- devices = adb_wrapper.AdbWrapper.GetDevices()
+ devices = cls.HealthyDevices()
if not devices:
raise device_errors.NoDevicesError()
+
devices = [d if isinstance(d, cls) else cls(d) for d in devices]
if async:
return parallelizer.Parallelizer(devices)
else:
return parallelizer.SyncParallelizer(devices)
+
+ @classmethod
+ def HealthyDevices(cls):
+ blacklist = device_blacklist.ReadBlacklist()
+ def blacklisted(adb):
+ if adb.GetDeviceSerial() in blacklist:
+ logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial())
+ return True
+ return False
+
+ return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices()
+ if not blacklisted(adb)]
+
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 98e3539..4301e9d 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -16,13 +16,13 @@
import logging
import os
import re
-import signal
import sys
import unittest
from pylib import android_commands
from pylib import cmd_helper
from pylib import constants
+from pylib import device_signal
from pylib.device import adb_wrapper
from pylib.device import device_errors
from pylib.device import device_utils
@@ -114,6 +114,10 @@
def __exit__(self, exc_type, exc_val, exc_tb):
pass
+ @property
+ def name(self):
+ return self.file.name
+
class _PatchedFunction(object):
def __init__(self, patched=None, mocked=None):
@@ -582,6 +586,81 @@
self.assertEquals([output.rstrip()],
self.device.RunShellCommand(cmd, check_return=False))
+ def testRunShellCommand_largeOutput_enabled(self):
+ cmd = 'echo $VALUE'
+ temp_file = MockTempFile('/sdcard/temp-123')
+ cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+ with self.assertCalls(
+ (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+ temp_file),
+ (self.call.adb.Shell(cmd_redirect)),
+ (self.call.device.ReadFile(temp_file.name), 'something')):
+ self.assertEquals(
+ ['something'],
+ self.device.RunShellCommand(
+ cmd, large_output=True, check_return=True))
+
+ def testRunShellCommand_largeOutput_disabledNoTrigger(self):
+ cmd = 'something'
+ with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')):
+ with self.assertRaises(device_errors.AdbCommandFailedError):
+ self.device.RunShellCommand(cmd, check_return=True)
+
+ def testRunShellCommand_largeOutput_disabledTrigger(self):
+ cmd = 'echo $VALUE'
+ temp_file = MockTempFile('/sdcard/temp-123')
+ cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+ with self.assertCalls(
+ (self.call.adb.Shell(cmd), self.ShellError('', None)),
+ (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+ temp_file),
+ (self.call.adb.Shell(cmd_redirect)),
+ (self.call.device.ReadFile(mock.ANY), 'something')):
+ self.assertEquals(['something'],
+ self.device.RunShellCommand(cmd, check_return=True))
+
+
+class DeviceUtilsRunPipedShellCommandTest(DeviceUtilsTest):
+
+ def testRunPipedShellCommand_success(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+ check_return=True),
+ ['This line contains foo', 'PIPESTATUS: 0 0']):
+ self.assertEquals(['This line contains foo'],
+ self.device._RunPipedShellCommand('ps | grep foo'))
+
+ def testRunPipedShellCommand_firstCommandFails(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+ check_return=True),
+ ['PIPESTATUS: 1 0']):
+ with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+ self.device._RunPipedShellCommand('ps | grep foo')
+ self.assertEquals([1, 0], ec.exception.status)
+
+ def testRunPipedShellCommand_secondCommandFails(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+ check_return=True),
+ ['PIPESTATUS: 0 1']):
+ with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+ self.device._RunPipedShellCommand('ps | grep foo')
+ self.assertEquals([0, 1], ec.exception.status)
+
+ def testRunPipedShellCommand_outputCutOff(self):
+ with self.assertCall(
+ self.call.device.RunShellCommand(
+ 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+ check_return=True),
+ ['foo.bar'] * 256 + ['foo.ba']):
+ with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+ self.device._RunPipedShellCommand('ps | grep foo')
+ self.assertIs(None, ec.exception.status)
+
class DeviceUtilsGetDevicePieWrapper(DeviceUtilsTest):
@@ -604,53 +683,45 @@
@mock.patch('time.sleep', mock.Mock())
class DeviceUtilsKillAllTest(DeviceUtilsTest):
- def testKillAll_noMatchingProcesses(self):
- with self.assertCall(self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'):
+ def testKillAll_noMatchingProcessesFailure(self):
+ with self.assertCall(self.call.device.GetPids('test_process'), {}):
with self.assertRaises(device_errors.CommandFailedError):
self.device.KillAll('test_process')
+ def testKillAll_noMatchingProcessesQuiet(self):
+ with self.assertCall(self.call.device.GetPids('test_process'), {}):
+ self.assertEqual(0, self.device.KillAll('test_process', quiet=True))
+
def testKillAll_nonblocking(self):
with self.assertCalls(
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'u0_a1 1234 174 123456 54321 ffffffff 456789ab some.process\n'),
+ (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
(self.call.adb.Shell('kill -9 1234'), '')):
- self.assertEquals(1,
- self.device.KillAll('some.process', blocking=False))
+ self.assertEquals(
+ 1, self.device.KillAll('some.process', blocking=False))
def testKillAll_blocking(self):
with self.assertCalls(
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'u0_a1 1234 174 123456 54321 ffffffff 456789ab some.process\n'),
+ (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
(self.call.adb.Shell('kill -9 1234'), ''),
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'u0_a1 1234 174 123456 54321 ffffffff 456789ab some.process\n'),
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n')):
- self.assertEquals(1,
- self.device.KillAll('some.process', blocking=True))
+ (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
+ (self.call.device.GetPids('some.process'), [])):
+ self.assertEquals(
+ 1, self.device.KillAll('some.process', blocking=True))
def testKillAll_root(self):
with self.assertCalls(
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'u0_a1 1234 174 123456 54321 ffffffff 456789ab some.process\n'),
+ (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
(self.call.device.NeedsSU(), True),
(self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
- self.assertEquals(1,
- self.device.KillAll('some.process', as_root=True))
+ self.assertEquals(
+ 1, self.device.KillAll('some.process', as_root=True))
def testKillAll_sigterm(self):
with self.assertCalls(
- (self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'u0_a1 1234 174 123456 54321 ffffffff 456789ab some.process\n'),
+ (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
(self.call.adb.Shell('kill -15 1234'), '')):
- self.assertEquals(1,
- self.device.KillAll('some.process', signum=signal.SIGTERM))
+ self.assertEquals(
+ 1, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
class DeviceUtilsStartActivityTest(DeviceUtilsTest):
@@ -1078,7 +1149,8 @@
as_root=False, check_return=True),
['-rw-rw---- root foo 256 1970-01-01 00:00 file']),
(self.call.device.RunShellCommand(
- ['cat', '/read/this/test/file'], as_root=False, check_return=True),
+ ['cat', '/read/this/test/file'],
+ as_root=False, check_return=True),
['this is a test file'])):
self.assertEqual('this is a test file\n',
self.device.ReadFile('/read/this/test/file'))
@@ -1092,6 +1164,17 @@
with self.assertRaises(device_errors.CommandFailedError):
self.device.ReadFile('/this/file/does.not.exist')
+ def testReadFile_zeroSize(self):
+ with self.assertCalls(
+ (self.call.device.RunShellCommand(
+ ['ls', '-l', '/this/file/has/zero/size'],
+ as_root=False, check_return=True),
+ ['-r--r--r-- root foo 0 1970-01-01 00:00 zero_size_file']),
+ (self.call.device._ReadFileWithPull('/this/file/has/zero/size'),
+ 'but it has contents\n')):
+ self.assertEqual('but it has contents\n',
+ self.device.ReadFile('/this/file/has/zero/size'))
+
def testReadFile_withSU(self):
with self.assertCalls(
(self.call.device.RunShellCommand(
@@ -1350,38 +1433,43 @@
class DeviceUtilsGetPidsTest(DeviceUtilsTest):
def testGetPids_noMatches(self):
- with self.assertCall(self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'user 1000 100 1024 1024 ffffffff 00000000 no.match\n'):
+ with self.assertCall(
+ self.call.device._RunPipedShellCommand('ps | grep -F does.not.match'),
+ []):
self.assertEqual({}, self.device.GetPids('does.not.match'))
def testGetPids_oneMatch(self):
- with self.assertCall(self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'user 1000 100 1024 1024 ffffffff 00000000 not.a.match\n'
- 'user 1001 100 1024 1024 ffffffff 00000000 one.match\n'):
+ with self.assertCall(
+ self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
+ ['user 1001 100 1024 1024 ffffffff 00000000 one.match']):
self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match'))
def testGetPids_mutlipleMatches(self):
- with self.assertCall(self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'user 1000 100 1024 1024 ffffffff 00000000 not\n'
- 'user 1001 100 1024 1024 ffffffff 00000000 one.match\n'
- 'user 1002 100 1024 1024 ffffffff 00000000 two.match\n'
- 'user 1003 100 1024 1024 ffffffff 00000000 three.match\n'):
+ with self.assertCall(
+ self.call.device._RunPipedShellCommand('ps | grep -F match'),
+ ['user 1001 100 1024 1024 ffffffff 00000000 one.match',
+ 'user 1002 100 1024 1024 ffffffff 00000000 two.match',
+ 'user 1003 100 1024 1024 ffffffff 00000000 three.match']):
self.assertEqual(
{'one.match': '1001', 'two.match': '1002', 'three.match': '1003'},
self.device.GetPids('match'))
def testGetPids_exactMatch(self):
- with self.assertCall(self.call.adb.Shell('ps'),
- 'USER PID PPID VSIZE RSS WCHAN PC NAME\n'
- 'user 1000 100 1024 1024 ffffffff 00000000 not.exact.match\n'
- 'user 1234 100 1024 1024 ffffffff 00000000 exact.match\n'):
+ with self.assertCall(
+ self.call.device._RunPipedShellCommand('ps | grep -F exact.match'),
+ ['user 1000 100 1024 1024 ffffffff 00000000 not.exact.match',
+ 'user 1234 100 1024 1024 ffffffff 00000000 exact.match']):
self.assertEqual(
{'not.exact.match': '1000', 'exact.match': '1234'},
self.device.GetPids('exact.match'))
+ def testGetPids_quotable(self):
+ with self.assertCall(
+ self.call.device._RunPipedShellCommand("ps | grep -F 'my$process'"),
+ ['user 1234 100 1024 1024 ffffffff 00000000 my$process']):
+ self.assertEqual(
+ {'my$process': '1234'}, self.device.GetPids('my$process'))
+
class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest):
@@ -1404,8 +1492,8 @@
def testGetMemoryUsageForPid_validPid(self):
with self.assertCalls(
- (self.call.device.RunShellCommand(
- ['showmap', '1234'], as_root=True, check_return=True),
+ (self.call.device._RunPipedShellCommand(
+ 'showmap 1234 | grep TOTAL', as_root=True),
['100 101 102 103 104 105 106 107 TOTAL']),
(self.call.device.ReadFile('/proc/1234/status', as_root=True),
'VmHWM: 1024 kB\n')):
@@ -1424,8 +1512,8 @@
def testGetMemoryUsageForPid_noSmaps(self):
with self.assertCalls(
- (self.call.device.RunShellCommand(
- ['showmap', '4321'], as_root=True, check_return=True),
+ (self.call.device._RunPipedShellCommand(
+ 'showmap 4321 | grep TOTAL', as_root=True),
['cannot open /proc/4321/smaps: No such file or directory']),
(self.call.device.ReadFile('/proc/4321/status', as_root=True),
'VmHWM: 1024 kb\n')):
@@ -1433,8 +1521,8 @@
def testGetMemoryUsageForPid_noStatus(self):
with self.assertCalls(
- (self.call.device.RunShellCommand(
- ['showmap', '4321'], as_root=True, check_return=True),
+ (self.call.device._RunPipedShellCommand(
+ 'showmap 4321 | grep TOTAL', as_root=True),
['100 101 102 103 104 105 106 107 TOTAL']),
(self.call.device.ReadFile('/proc/4321/status', as_root=True),
self.CommandError())):
@@ -1451,116 +1539,6 @@
self.device.GetMemoryUsageForPid(4321))
-class DeviceUtilsGetBatteryInfoTest(DeviceUtilsTest):
- def testGetBatteryInfo_normal(self):
- with self.assertCall(
- self.call.device.RunShellCommand(
- ['dumpsys', 'battery'], check_return=True),
- [
- 'Current Battery Service state:',
- ' AC powered: false',
- ' USB powered: true',
- ' level: 100',
- ' temperature: 321',
- ]):
- self.assertEquals(
- {
- 'AC powered': 'false',
- 'USB powered': 'true',
- 'level': '100',
- 'temperature': '321',
- },
- self.device.GetBatteryInfo())
-
-
- def testGetBatteryInfo_nothing(self):
- with self.assertCall(
- self.call.device.RunShellCommand(
- ['dumpsys', 'battery'], check_return=True), []):
- self.assertEquals({}, self.device.GetBatteryInfo())
-
-
-class DeviceUtilsGetChargingTest(DeviceUtilsTest):
- def testGetCharging_usb(self):
- with self.assertCall(
- self.call.device.GetBatteryInfo(), {'USB powered': 'true'}):
- self.assertTrue(self.device.GetCharging())
-
- def testGetCharging_usbFalse(self):
- with self.assertCall(
- self.call.device.GetBatteryInfo(), {'USB powered': 'false'}):
- self.assertFalse(self.device.GetCharging())
-
- def testGetCharging_ac(self):
- with self.assertCall(
- self.call.device.GetBatteryInfo(), {'AC powered': 'true'}):
- self.assertTrue(self.device.GetCharging())
-
- def testGetCharging_wireless(self):
- with self.assertCall(
- self.call.device.GetBatteryInfo(), {'Wireless powered': 'true'}):
- self.assertTrue(self.device.GetCharging())
-
- def testGetCharging_unknown(self):
- with self.assertCall(
- self.call.device.GetBatteryInfo(), {'level': '42'}):
- self.assertFalse(self.device.GetCharging())
-
-
-class DeviceUtilsSetChargingTest(DeviceUtilsTest):
-
- @mock.patch('time.sleep', mock.Mock())
- def testSetCharging_enabled(self):
- with self.assertCalls(
- (self.call.device.FileExists(mock.ANY), True),
- (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
- (self.call.device.GetCharging(), False),
- (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
- (self.call.device.GetCharging(), True)):
- self.device.SetCharging(True)
-
- def testSetCharging_alreadyEnabled(self):
- with self.assertCalls(
- (self.call.device.FileExists(mock.ANY), True),
- (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
- (self.call.device.GetCharging(), True)):
- self.device.SetCharging(True)
-
- @mock.patch('time.sleep', mock.Mock())
- def testSetCharging_disabled(self):
- with self.assertCalls(
- (self.call.device.FileExists(mock.ANY), True),
- (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
- (self.call.device.GetCharging(), True),
- (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
- (self.call.device.GetCharging(), False)):
- self.device.SetCharging(False)
-
-
-class DeviceUtilsSetBatteryMeasurementTest(DeviceUtilsTest):
-
- def testBatteryMeasurement(self):
- with self.assertCalls(
- (self.call.device.RunShellCommand(
- mock.ANY, retries=0, single_line=True,
- timeout=10, check_return=True), '22'),
- (self.call.device.RunShellCommand(
- ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
- (self.call.device.RunShellCommand(
- ['dumpsys', 'batterystats', '--charged', '--checkin'],
- check_return=True), []),
- (self.call.device.RunShellCommand(
- ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
- (self.call.device.GetCharging(), False),
- (self.call.device.RunShellCommand(
- ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True), []),
- (self.call.device.RunShellCommand(
- ['dumpsys', 'battery', 'reset'], check_return=True), []),
- (self.call.device.GetCharging(), True)):
- with self.device.BatteryMeasurement():
- pass
-
-
class DeviceUtilsStrTest(DeviceUtilsTest):
def testStr_returnsSerial(self):
@@ -1569,27 +1547,83 @@
self.assertEqual('0123456789abcdef', str(self.device))
+class DeviceUtilsClientCache(DeviceUtilsTest):
+
+ def testClientCache_twoCaches(self):
+ self.device._cache['test'] = 0
+ client_cache_one = self.device.GetClientCache('ClientOne')
+ client_cache_one['test'] = 1
+ client_cache_two = self.device.GetClientCache('ClientTwo')
+ client_cache_two['test'] = 2
+ self.assertEqual(self.device._cache, {'test': 0})
+ self.assertEqual(client_cache_one, {'test': 1})
+ self.assertEqual(client_cache_two, {'test': 2})
+ self.device._ClearCache()
+ self.assertEqual(self.device._cache, {})
+ self.assertEqual(client_cache_one, {})
+ self.assertEqual(client_cache_two, {})
+
+ def testClientCache_multipleInstances(self):
+ client_cache_one = self.device.GetClientCache('ClientOne')
+ client_cache_one['test'] = 1
+ client_cache_two = self.device.GetClientCache('ClientOne')
+ self.assertEqual(client_cache_one, {'test': 1})
+ self.assertEqual(client_cache_two, {'test': 1})
+ self.device._ClearCache()
+ self.assertEqual(client_cache_one, {})
+ self.assertEqual(client_cache_two, {})
+
+
class DeviceUtilsParallelTest(mock_calls.TestCase):
def testParallel_default(self):
test_serials = ['0123456789abcdef', 'fedcba9876543210']
with self.assertCall(
- mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(),
- [_AdbWrapperMock(serial) for serial in test_serials]):
+ mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(),
+ [device_utils.DeviceUtils(s) for s in test_serials]):
parallel_devices = device_utils.DeviceUtils.parallel()
for serial, device in zip(test_serials, parallel_devices.pGet(None)):
- self.assertTrue(
- isinstance(device, device_utils.DeviceUtils)
- and serial == str(device),
- 'Expected a DeviceUtils object with serial %s' % serial)
+ self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+ self.assertEquals(serial, device.adb.GetDeviceSerial())
def testParallel_noDevices(self):
with self.assertCall(
- mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(), []):
+ mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(), []):
with self.assertRaises(device_errors.NoDevicesError):
device_utils.DeviceUtils.parallel()
+class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
+
+ def _createAdbWrapperMock(self, serial, is_ready=True):
+ adb = _AdbWrapperMock(serial)
+ adb.is_ready = is_ready
+ return adb
+
+ def testHealthyDevices_default(self):
+ test_serials = ['0123456789abcdef', 'fedcba9876543210']
+ with self.assertCalls(
+ (mock.call.pylib.device.device_blacklist.ReadBlacklist(), []),
+ (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+ [self._createAdbWrapperMock(s) for s in test_serials])):
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ for serial, device in zip(test_serials, devices):
+ self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+ self.assertEquals(serial, device.adb.GetDeviceSerial())
+
+ def testHealthyDevices_blacklisted(self):
+ test_serials = ['0123456789abcdef', 'fedcba9876543210']
+ with self.assertCalls(
+ (mock.call.pylib.device.device_blacklist.ReadBlacklist(),
+ ['fedcba9876543210']),
+ (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+ [self._createAdbWrapperMock(s) for s in test_serials])):
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ self.assertEquals(1, len(devices))
+ self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils))
+ self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial())
+
+
if __name__ == '__main__':
logging.getLogger().setLevel(logging.DEBUG)
unittest.main(verbosity=2)
diff --git a/build/android/pylib/device_signal.py b/build/android/pylib/device_signal.py
new file mode 100644
index 0000000..6a5b709
--- /dev/null
+++ b/build/android/pylib/device_signal.py
@@ -0,0 +1,41 @@
+# 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 constants for signals that should be supported on devices.
+
+Note: Obtained by running `kill -l` on a user device.
+"""
+
+
+SIGHUP = 1 # Hangup
+SIGINT = 2 # Interrupt
+SIGQUIT = 3 # Quit
+SIGILL = 4 # Illegal instruction
+SIGTRAP = 5 # Trap
+SIGABRT = 6 # Aborted
+SIGBUS = 7 # Bus error
+SIGFPE = 8 # Floating point exception
+SIGKILL = 9 # Killed
+SIGUSR1 = 10 # User signal 1
+SIGSEGV = 11 # Segmentation fault
+SIGUSR2 = 12 # User signal 2
+SIGPIPE = 13 # Broken pipe
+SIGALRM = 14 # Alarm clock
+SIGTERM = 15 # Terminated
+SIGSTKFLT = 16 # Stack fault
+SIGCHLD = 17 # Child exited
+SIGCONT = 18 # Continue
+SIGSTOP = 19 # Stopped (signal)
+SIGTSTP = 20 # Stopped
+SIGTTIN = 21 # Stopped (tty input)
+SIGTTOU = 22 # Stopped (tty output)
+SIGURG = 23 # Urgent I/O condition
+SIGXCPU = 24 # CPU time limit exceeded
+SIGXFSZ = 25 # File size limit exceeded
+SIGVTALRM = 26 # Virtual timer expired
+SIGPROF = 27 # Profiling timer expired
+SIGWINCH = 28 # Window size changed
+SIGIO = 29 # I/O possible
+SIGPWR = 30 # Power failure
+SIGSYS = 31 # Bad system call
diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py
index eb83d68..d16b9b1 100644
--- a/build/android/pylib/forwarder.py
+++ b/build/android/pylib/forwarder.py
@@ -288,11 +288,8 @@
self._device_forwarder_path_on_host,
Forwarder._DEVICE_FORWARDER_FOLDER)])
cmd = '%s %s' % (tool.GetUtilWrapper(), Forwarder._DEVICE_FORWARDER_PATH)
- (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
- cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
- if exit_code != 0:
- raise Exception(
- 'Failed to start device forwarder:\n%s' % '\n'.join(output))
+ device.RunShellCommand(
+ cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
self._initialized_devices.add(device_serial)
def _KillHostLocked(self):
@@ -328,5 +325,5 @@
cmd = '%s %s --kill-server' % (tool.GetUtilWrapper(),
Forwarder._DEVICE_FORWARDER_PATH)
- device.old_interface.GetAndroidToolStatusAndOutput(
- cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
+ device.RunShellCommand(
+ cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled
index 3c36264..39eff4d 100644
--- a/build/android/pylib/gtest/filter/content_browsertests_disabled
+++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -2,13 +2,6 @@
# Timeouts
Http/MediaTest.*
File/MediaTest.*
-WorkerTest.IncognitoSharedWorkers
-WorkerTest.MultipleSharedWorkers
-WorkerTest.PassMessagePortToSharedWorker
-WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect
-WorkerTest.SharedWorkerHttpAuth
-WorkerTest.SingleSharedWorker
-WorkerTest.WebSocketSharedWorker
MediaTest.*
DatabaseTest.*
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index 8608ed7..6ce0fb1 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -6,6 +6,7 @@
# Add new suites here before upgrading them to the stable list below.
EXPERIMENTAL_TEST_SUITES = [
+ 'components_browsertests',
'content_gl_tests',
'heap_profiler_unittests',
'devtools_bridge_tests',
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index 186b8fc..b6f83b3 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -92,9 +92,10 @@
raise ValueError('Platform mode currently supports only 1 gtest suite')
self._suite = args.suite_name[0]
- if self._suite == 'content_browsertests':
- error_func('content_browsertests are not currently supported '
- 'in platform mode.')
+ if (self._suite == 'content_browsertests' or
+ self._suite == 'components_browsertests'):
+ error_func('%s are not currently supported '
+ 'in platform mode.' % self._suite)
self._apk_path = os.path.join(
constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite)
else:
diff --git a/build/android/pylib/gtest/local_device_gtest_run.py b/build/android/pylib/gtest/local_device_gtest_run.py
index c48c865..fd143d6 100644
--- a/build/android/pylib/gtest/local_device_gtest_run.py
+++ b/build/android/pylib/gtest/local_device_gtest_run.py
@@ -30,7 +30,8 @@
# TODO(jbudorick): Move this up to the test instance if the net test server is
# handled outside of the APK for the remote_device environment.
_SUITE_REQUIRES_TEST_SERVER_SPAWNER = [
- 'content_unittests', 'content_browsertests', 'net_unittests', 'unit_tests'
+ 'components_browsertests', 'content_unittests', 'content_browsertests',
+ 'net_unittests', 'unit_tests'
]
class _ApkDelegate(object):
@@ -112,12 +113,7 @@
return output
def Clear(self, device):
- try:
- device.KillAll(self._exe_file_name, blocking=True, timeout=30, retries=0)
- except device_errors.CommandFailedError:
- # Raised if there is no process with the given name, which in this case
- # is all we care about.
- pass
+ device.KillAll(self._exe_file_name, blocking=True, timeout=30, quiet=True)
class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py
index 1b882ca..44662d0 100644
--- a/build/android/pylib/gtest/setup.py
+++ b/build/android/pylib/gtest/setup.py
@@ -31,6 +31,7 @@
'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate',
'breakpad_unittests': 'breakpad/breakpad_unittests.isolate',
'cc_perftests': 'cc/cc_perftests.isolate',
+ 'components_browsertests': 'components/components_browsertests.isolate',
'components_unittests': 'components/components_unittests.isolate',
'content_browsertests': 'content/content_browsertests.isolate',
'content_unittests': 'content/content_unittests.isolate',
@@ -236,7 +237,8 @@
tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter)
# Coalesce unit tests into a single test per device
- if test_options.suite_name != 'content_browsertests':
+ if (test_options.suite_name != 'content_browsertests' and
+ test_options.suite_name != 'components_browsertests'):
num_devices = len(devices)
tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)]
tests = [t for t in tests if t]
diff --git a/build/android/pylib/gtest/test_options.py b/build/android/pylib/gtest/test_options.py
index 5099ba6..58cd82b 100644
--- a/build/android/pylib/gtest/test_options.py
+++ b/build/android/pylib/gtest/test_options.py
@@ -8,7 +8,6 @@
GTestOptions = collections.namedtuple('GTestOptions', [
'tool',
- 'cleanup_test_files',
'gtest_filter',
'run_disabled',
'test_arguments',
diff --git a/build/android/pylib/gtest/test_package_apk.py b/build/android/pylib/gtest/test_package_apk.py
index cdb6daf..8da3c74 100644
--- a/build/android/pylib/gtest/test_package_apk.py
+++ b/build/android/pylib/gtest/test_package_apk.py
@@ -34,6 +34,10 @@
self.suite_path = os.path.join(
constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
self._package_info = constants.PACKAGE_INFO['content_browsertests']
+ elif suite_name == 'components_browsertests':
+ self.suite_path = os.path.join(
+ constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
+ self._package_info = constants.PACKAGE_INFO['components_browsertests']
else:
self.suite_path = os.path.join(
constants.GetOutDirectory(), '%s_apk' % suite_name,
@@ -46,7 +50,7 @@
def _GetFifo(self):
# The test.fifo path is determined by:
- # testing/android/java/src/org/chromium/native_test/
+ # testing/android/native_test/java/src/org/chromium/native_test/
# ChromeNativeTestActivity.java and
# testing/android/native_test_launcher.cc
return '/data/data/' + self._package_info.package + '/files/test.fifo'
@@ -90,6 +94,15 @@
# TODO(jbudorick) Handle this exception appropriately once the
# conversions are done.
pass
+ elif self.suite_name == 'components_browsertests':
+ try:
+ device.RunShellCommand(
+ 'rm -r %s/components_shell' % device.GetExternalStoragePath(),
+ timeout=60 * 2)
+ except device_errors.CommandFailedError:
+ # TODO(jbudorick) Handle this exception appropriately once the
+ # conversions are done.
+ pass
#override
def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
diff --git a/build/android/pylib/gtest/test_package_exe.py b/build/android/pylib/gtest/test_package_exe.py
index e607cad..aa3374e 100644
--- a/build/android/pylib/gtest/test_package_exe.py
+++ b/build/android/pylib/gtest/test_package_exe.py
@@ -6,6 +6,7 @@
import logging
import os
+import posixpath
import sys
import tempfile
@@ -78,15 +79,7 @@
#override
def ClearApplicationState(self, device):
- try:
- # We don't expect the executable to be running, so we don't attempt
- # to retry on failure.
- device.KillAll(self.suite_name, blocking=True, timeout=30, retries=0)
- except device_errors.CommandFailedError:
- # KillAll raises an exception if it can't find a process with the given
- # name. We only care that there is no process with the given name, so
- # we can safely eat the exception.
- pass
+ device.KillAll(self.suite_name, blocking=True, timeout=30, quiet=True)
#override
def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
@@ -119,14 +112,19 @@
#override
def GetAllTests(self, device):
- cmd = '%s %s/%s --gtest_list_tests' % (self.tool.GetTestWrapper(),
- constants.TEST_EXECUTABLE_DIR, self.suite_name)
- lib_path = '%s/%s_deps' % (constants.TEST_EXECUTABLE_DIR, self.suite_name)
- (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
- cmd, lib_path=lib_path)
- if exit_code != 0:
- raise Exception(
- 'Failed to start binary:\n%s' % '\n'.join(output))
+ lib_path = posixpath.join(
+ constants.TEST_EXECUTABLE_DIR, '%s_deps' % self.suite_name)
+
+ cmd = []
+ for wrapper in (device.GetDevicePieWrapper(), self.tool.GetTestWrapper()):
+ if wrapper:
+ cmd.append(wrapper)
+ cmd.extend([
+ posixpath.join(constants.TEST_EXECUTABLE_DIR, self.suite_name),
+ '--gtest_list_tests'])
+
+ output = device.RunShellCommand(
+ cmd, check_return=True, env={'LD_LIBRARY_PATH': lib_path})
return gtest_test_instance.ParseGTestListTests(output)
#override
diff --git a/build/android/pylib/gtest/test_runner.py b/build/android/pylib/gtest/test_runner.py
index 4bb9737..4926388 100644
--- a/build/android/pylib/gtest/test_runner.py
+++ b/build/android/pylib/gtest/test_runner.py
@@ -26,10 +26,15 @@
# to output the CRASHED marker when a crash happens.
RE_CRASH = re.compile('\\[ CRASHED \\](.*)\r\n')
+# Bots that don't output anything for 20 minutes get timed out, so that's our
+# hard cap.
+_INFRA_STDOUT_TIMEOUT = 20 * 60
+
def _TestSuiteRequiresMockTestServer(suite_name):
"""Returns True if the test suite requires mock test server."""
tests_require_net_test_server = ['unit_tests', 'net_unittests',
+ 'components_browsertests',
'content_unittests',
'content_browsertests']
return (suite_name in
@@ -49,8 +54,7 @@
test_package: An instance of TestPackage class.
"""
- super(TestRunner, self).__init__(device, test_options.tool,
- test_options.cleanup_test_files)
+ super(TestRunner, self).__init__(device, test_options.tool)
self.test_package = test_package
self.test_package.tool = self.tool
@@ -63,7 +67,8 @@
if os.environ.get('BUILDBOT_SLAVENAME'):
timeout = timeout * 2
- self._timeout = timeout * self.tool.GetTimeoutScale()
+ self._timeout = min(timeout * self.tool.GetTimeoutScale(),
+ _INFRA_STDOUT_TIMEOUT)
if _TestSuiteRequiresHighPerfMode(self.test_package.suite_name):
self._perf_controller = perf_control.PerfControl(self.device)
diff --git a/build/android/pylib/host_driven/setup.py b/build/android/pylib/host_driven/setup.py
index 285bcd4..b2ed348 100644
--- a/build/android/pylib/host_driven/setup.py
+++ b/build/android/pylib/host_driven/setup.py
@@ -195,7 +195,6 @@
def TestRunnerFactory(device, shard_index):
return test_runner.HostDrivenTestRunner(
device, shard_index,
- instrumentation_options.tool,
- instrumentation_options.cleanup_test_files)
+ instrumentation_options.tool)
return (TestRunnerFactory, available_tests)
diff --git a/build/android/pylib/host_driven/test_case.py b/build/android/pylib/host_driven/test_case.py
index 8c372cd..a7c6a18 100644
--- a/build/android/pylib/host_driven/test_case.py
+++ b/build/android/pylib/host_driven/test_case.py
@@ -50,8 +50,6 @@
instrumentation_options: An InstrumentationOptions object.
"""
class_name = self.__class__.__name__
- self.adb = None
- self.cleanup_test_files = False
self.device = None
self.device_id = ''
self.has_forwarded_ports = False
@@ -67,15 +65,12 @@
# TODO(bulach): make ports_to_forward not optional and move the Forwarder
# mapping here.
- def SetUp(self, device, shard_index,
- cleanup_test_files, ports_to_forward=None):
+ def SetUp(self, device, shard_index, ports_to_forward=None):
if not ports_to_forward:
ports_to_forward = []
self.device_id = device
self.shard_index = shard_index
self.device = device_utils.DeviceUtils(self.device_id)
- self.adb = self.device.old_interface
- self.cleanup_test_files = cleanup_test_files
if ports_to_forward:
self.ports_to_forward = ports_to_forward
diff --git a/build/android/pylib/host_driven/test_runner.py b/build/android/pylib/host_driven/test_runner.py
index 865be20..5e175bc 100644
--- a/build/android/pylib/host_driven/test_runner.py
+++ b/build/android/pylib/host_driven/test_runner.py
@@ -47,23 +47,27 @@
result, rather than being re-raised on the main thread.
"""
+ # TODO(jbudorick): Remove cleanup_test_files once it's no longer used.
+ # pylint: disable=unused-argument
#override
- def __init__(self, device, shard_index, tool, cleanup_test_files):
+ def __init__(self, device, shard_index, tool, cleanup_test_files=None):
"""Creates a new HostDrivenTestRunner.
Args:
device: Attached android device.
shard_index: Shard index.
tool: Name of the Valgrind tool.
- cleanup_test_files: Whether or not to cleanup test files on device.
+ cleanup_test_files: Deprecated.
"""
- super(HostDrivenTestRunner, self).__init__(device, tool, cleanup_test_files)
+ super(HostDrivenTestRunner, self).__init__(device, tool)
# The shard index affords the ability to create unique port numbers (e.g.
# DEFAULT_PORT + shard_index) if the test so wishes.
self.shard_index = shard_index
+ # pylint: enable=unused-argument
+
#override
def RunTest(self, test):
"""Sets up and runs a test case.
@@ -82,7 +86,7 @@
exception_raised = False
try:
- test.SetUp(str(self.device), self.shard_index, self._cleanup_test_files)
+ test.SetUp(str(self.device), self.shard_index)
except Exception:
logging.exception(
'Caught exception while trying to run SetUp() for test: ' +
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 3f56e6d..ccc0e72 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -335,7 +335,7 @@
with open(pickle_path, 'r') as pickle_file:
pickle_data = pickle.loads(pickle_file.read())
- jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+ jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
try:
if pickle_data['VERSION'] != _PICKLE_FORMAT_VERSION:
@@ -377,7 +377,7 @@
if is_test_class(c)]
def _SaveTestsToPickle(self, pickle_path, jar_path, tests):
- jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+ jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
pickle_data = {
'VERSION': _PICKLE_FORMAT_VERSION,
'JAR_MD5SUM': jar_md5,
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py
index c3faef3..9c38510 100644
--- a/build/android/pylib/instrumentation/test_jar.py
+++ b/build/android/pylib/instrumentation/test_jar.py
@@ -65,7 +65,7 @@
try:
with open(self._pickled_proguard_name, 'r') as r:
d = pickle.loads(r.read())
- jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash
+ jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]
if (d['JAR_MD5SUM'] == jar_md5 and
d['VERSION'] == PICKLE_FORMAT_VERSION):
self._test_methods = d['TEST_METHODS']
@@ -105,7 +105,8 @@
logging.info('Storing proguard output to %s', self._pickled_proguard_name)
d = {'VERSION': PICKLE_FORMAT_VERSION,
'TEST_METHODS': self._test_methods,
- 'JAR_MD5SUM': md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash}
+ 'JAR_MD5SUM':
+ md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]}
with open(self._pickled_proguard_name, 'w') as f:
f.write(pickle.dumps(d))
diff --git a/build/android/pylib/instrumentation/test_options.py b/build/android/pylib/instrumentation/test_options.py
index 4a16b11..792010b 100644
--- a/build/android/pylib/instrumentation/test_options.py
+++ b/build/android/pylib/instrumentation/test_options.py
@@ -8,7 +8,6 @@
InstrumentationOptions = collections.namedtuple('InstrumentationOptions', [
'tool',
- 'cleanup_test_files',
'annotations',
'exclude_annotations',
'test_filter',
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index f3983fd..6e8be34 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -48,8 +48,7 @@
test_pkg: A TestPackage object.
additional_flags: A list of additional flags to add to the command line.
"""
- super(TestRunner, self).__init__(device, test_options.tool,
- test_options.cleanup_test_files)
+ super(TestRunner, self).__init__(device, test_options.tool)
self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index
self._logcat_monitor = None
@@ -229,7 +228,7 @@
# just quits and does not do anything. The java test harness will still
# print the appropriate annotation for us, but will add --NORUN-- for
# us so we know to ignore the results.
- # The --NORUN-- tag is managed by MainActivityTestBase.java
+ # The --NORUN-- tag is managed by ChromeTabbedActivityTestBase.java
if regex.group(1) != '--NORUN--':
# Obtain the relevant perf data. The data is dumped to a
diff --git a/build/android/pylib/junit/test_dispatcher.py b/build/android/pylib/junit/test_dispatcher.py
index b821b75..6e0d865 100644
--- a/build/android/pylib/junit/test_dispatcher.py
+++ b/build/android/pylib/junit/test_dispatcher.py
@@ -2,6 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from pylib import constants
+from pylib.base import base_test_result
+
def RunTests(tests, runner_factory):
"""Runs a set of java tests on the host.
@@ -11,9 +14,15 @@
def run(t):
runner = runner_factory(None, None)
runner.SetUp()
- result = runner.RunTest(t)
+ results_list, return_code = runner.RunTest(t)
runner.TearDown()
- return result == 0
+ return (results_list, return_code == 0)
- return (None, 0 if all(run(t) for t in tests) else 1)
-
+ test_run_results = base_test_result.TestRunResults()
+ exit_code = 0
+ for t in tests:
+ results_list, passed = run(t)
+ test_run_results.AddResults(results_list)
+ if not passed:
+ exit_code = constants.ERROR_EXIT_CODE
+ return (test_run_results, exit_code)
\ No newline at end of file
diff --git a/build/android/pylib/junit/test_runner.py b/build/android/pylib/junit/test_runner.py
index b85967b..a6d3bf9 100644
--- a/build/android/pylib/junit/test_runner.py
+++ b/build/android/pylib/junit/test_runner.py
@@ -2,10 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import json
import os
+import tempfile
from pylib import cmd_helper
from pylib import constants
+from pylib.base import base_test_result
+from pylib.results import json_results
class JavaTestRunner(object):
"""Runs java tests on the host."""
@@ -22,22 +26,24 @@
def RunTest(self, _test):
"""Runs junit tests from |self._test_suite|."""
-
- command = ['java',
- '-Drobolectric.dependency.dir=%s' %
- os.path.join(constants.GetOutDirectory(), 'lib.java'),
- '-jar', os.path.join(constants.GetOutDirectory(), 'lib.java',
- '%s.jar' % self._test_suite)]
-
- if self._test_filter:
- command.extend(['-gtest-filter', self._test_filter])
- if self._package_filter:
- command.extend(['-package-filter', self._package_filter])
- if self._runner_filter:
- command.extend(['-runner-filter', self._runner_filter])
- if self._sdk_version:
- command.extend(['-sdk-version', self._sdk_version])
- return cmd_helper.RunCmd(command)
+ with tempfile.NamedTemporaryFile() as json_file:
+ java_script = os.path.join(
+ constants.GetOutDirectory(), 'bin', self._test_suite)
+ command = [java_script,
+ '-test-jars', self._test_suite + '.jar',
+ '-json-results-file', json_file.name]
+ if self._test_filter:
+ command.extend(['-gtest-filter', self._test_filter])
+ if self._package_filter:
+ command.extend(['-package-filter', self._package_filter])
+ if self._runner_filter:
+ command.extend(['-runner-filter', self._runner_filter])
+ if self._sdk_version:
+ command.extend(['-sdk-version', self._sdk_version])
+ return_code = cmd_helper.RunCmd(command)
+ results_list = json_results.ParseResultsFromJson(
+ json.loads(json_file.read()))
+ return (results_list, return_code)
def TearDown(self):
pass
diff --git a/build/android/pylib/linker/setup.py b/build/android/pylib/linker/setup.py
index ff21f10..5776f5a 100644
--- a/build/android/pylib/linker/setup.py
+++ b/build/android/pylib/linker/setup.py
@@ -40,7 +40,6 @@
if t.qualified_name in filtered_test_names]
def TestRunnerFactory(device, _shard_index):
- return test_runner.LinkerTestRunner(
- device, args.tool, args.cleanup_test_files)
+ return test_runner.LinkerTestRunner(device, args.tool)
return (TestRunnerFactory, all_tests)
diff --git a/build/android/pylib/linker/test_runner.py b/build/android/pylib/linker/test_runner.py
index 3680f83..b6803e4 100644
--- a/build/android/pylib/linker/test_runner.py
+++ b/build/android/pylib/linker/test_runner.py
@@ -49,16 +49,14 @@
"""
#override
- def __init__(self, device, tool, cleanup_test_files):
+ def __init__(self, device, tool):
"""Creates a new LinkerTestRunner.
Args:
device: Attached android device.
tool: Name of the Valgrind tool.
- cleanup_test_files: Whether or not to cleanup test files on device.
"""
-
- super(LinkerTestRunner, self).__init__(device, tool, cleanup_test_files)
+ super(LinkerTestRunner, self).__init__(device, tool)
#override
def InstallTestPackage(self):
@@ -68,8 +66,7 @@
if not os.path.exists(apk_path):
raise Exception('%s not found, please build it' % apk_path)
- package_name = apk_helper.GetPackageName(apk_path)
- self.device.old_interface.ManagedInstall(apk_path, package_name)
+ self.device.Install(apk_path)
#override
def RunTest(self, test):
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 72acb6e..0d02ca3 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -13,26 +13,24 @@
def __init__(self, args, _error_func):
super(LocalDeviceEnvironment, self).__init__()
- self._device = args.test_device
+ self._device_serial = args.test_device
self._devices = []
self._max_tries = 1 + args.num_retries
self._tool_name = args.tool
#override
def SetUp(self):
- # TODO(jbudorick): This can be refined to support filters etc.
- available_devices = adb_wrapper.AdbWrapper.GetDevices()
+ available_devices = device_utils.DeviceUtils.HealthyDevices()
if not available_devices:
raise device_errors.NoDevicesError
- if self._device:
- if self._device not in available_devices:
+ if self._device_serial:
+ self._devices = [d for d in available_devices
+ if d.adb.GetDeviceSerial == self._device_serial]
+ if not self._devices:
raise device_errors.DeviceUnreachableError(
- 'Could not find device %r' % self._device)
- self._devices = [device_utils.DeviceUtils(self._device)]
+ 'Could not find device %r' % self._device_serial)
else:
- self._devices = [
- device_utils.DeviceUtils(s)
- for s in available_devices]
+ self._devices = available_devices
@property
def devices(self):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index ac3f5b1..adc1037 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -3,11 +3,14 @@
# found in the LICENSE file.
import logging
+import re
import time
from pylib import flag_changer
from pylib.base import base_test_result
from pylib.base import test_run
+from pylib.constants import keyevent
+from pylib.device import device_errors
from pylib.local.device import local_device_test_run
@@ -27,16 +30,39 @@
def DidPackageCrashOnDevice(package_name, device):
# Dismiss any error dialogs. Limit the number in case we have an error
# loop or we are failing to dismiss.
- for _ in xrange(10):
- package = device.old_interface.DismissCrashDialogIfNeeded()
- if not package:
- return False
- # Assume test package convention of ".test" suffix
- if package in package_name:
- return True
+ try:
+ for _ in xrange(10):
+ package = _DismissCrashDialog(device)
+ if not package:
+ return False
+ # Assume test package convention of ".test" suffix
+ if package in package_name:
+ return True
+ except device_errors.CommandFailedError:
+ logging.exception('Error while attempting to dismiss crash dialog.')
return False
+_CURRENT_FOCUS_CRASH_RE = re.compile(
+ r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')
+
+
+def _DismissCrashDialog(device):
+ # TODO(jbudorick): Try to grep the output on the device instead of using
+ # large_output if/when DeviceUtils exposes a public interface for piped
+ # shell command handling.
+ for l in device.RunShellCommand(
+ ['dumpsys', 'window', 'windows'], check_return=True, large_output=True):
+ m = re.match(_CURRENT_FOCUS_CRASH_RE, l)
+ if m:
+ device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+ device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+ device.SendKeyEvent(keyevent.KEYCODE_ENTER)
+ return m.group(2)
+
+ return None
+
+
class LocalDeviceInstrumentationTestRun(
local_device_test_run.LocalDeviceTestRun):
def __init__(self, env, test_instance):
diff --git a/build/android/pylib/monkey/test_runner.py b/build/android/pylib/monkey/test_runner.py
index 19dd339..3fd1797 100644
--- a/build/android/pylib/monkey/test_runner.py
+++ b/build/android/pylib/monkey/test_runner.py
@@ -10,8 +10,11 @@
from pylib import constants
from pylib.base import base_test_result
from pylib.base import base_test_runner
+from pylib.device import device_errors
from pylib.device import intent
+_CHROME_PACKAGE = constants.PACKAGE_INFO['chrome'].package
+
class TestRunner(base_test_runner.BaseTestRunner):
"""A TestRunner instance runs a monkey test on a single device."""
@@ -87,9 +90,17 @@
test_name, base_test_result.ResultType.FAIL, log=output)
if 'chrome' in self._options.package:
logging.warning('Starting MinidumpUploadService...')
+ # TODO(jbudorick): Update this after upstreaming.
+ minidump_intent = intent.Intent(
+ action='%s.crash.ACTION_FIND_ALL' % _CHROME_PACKAGE,
+ package=self._package,
+ activity='%s.crash.MinidumpUploadService' % _CHROME_PACKAGE)
try:
- self.device.old_interface.StartCrashUploadService(self._package)
- except AssertionError as e:
- logging.error('Failed to start MinidumpUploadService: %s', e)
+ self.device.RunShellCommand(
+ ['am', 'startservice'] + minidump_intent.am_args,
+ as_root=True, check_return=True)
+ except device_errors.CommandFailedError:
+ logging.exception('Failed to start MinidumpUploadService')
+
results.AddResult(result)
return results, False
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
index 97fa4a7..b6a0989 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -28,7 +28,7 @@
def SetHighPerfMode(self):
"""Sets the highest stable performance mode for the device."""
- if not self._device.old_interface.IsRootEnabled():
+ if not self._device.HasRoot():
message = 'Need root for performance mode. Results may be NOISY!!'
logging.warning(message)
# Add an additional warning at exit, such that it's clear that any results
@@ -58,13 +58,13 @@
self._ForceAllCpusOnline(True)
self._SetScalingGovernorInternal('performance')
if not self._AllCpusAreOnline():
- if not self._device.old_interface.IsRootEnabled():
+ if not self._device.HasRoot():
raise RuntimeError('Need root to force CPUs online.')
raise RuntimeError('Failed to force CPUs online.')
def SetDefaultPerfMode(self):
"""Sets the performance mode for the device to its default mode."""
- if not self._device.old_interface.IsRootEnabled():
+ if not self._device.HasRoot():
return
product_model = self._device.product_model
if 'Nexus 5' == product_model:
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index da66d07..9d1f437 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -170,7 +170,7 @@
tests: a dict mapping test_name to command.
flaky_tests: a list of flaky test_name.
"""
- super(TestRunner, self).__init__(device, None, 'Release')
+ super(TestRunner, self).__init__(device, None)
self._options = test_options
self._shard_index = shard_index
self._max_shard = max_shard
diff --git a/build/android/pylib/remote/device/appurify_constants.py b/build/android/pylib/remote/device/appurify_constants.py
new file mode 100644
index 0000000..9343178
--- /dev/null
+++ b/build/android/pylib/remote/device/appurify_constants.py
@@ -0,0 +1,57 @@
+# 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 a set of constants specific to appurify."""
+
+# Appurify network config constants.
+class NETWORK(object):
+ WIFI_1_BAR = 1
+ SPRINT_4G_LTE_4_BARS = 2
+ SPRINT_3G_5_BARS = 3
+ SPRINT_3G_4_BARS = 4
+ SPRINT_3G_3_BARS = 5
+ SPRINT_3G_2_BARS = 6
+ SPRINT_3G_1_BAR = 7
+ SPRING_4G_1_BAR = 8
+ VERIZON_3G_5_BARS = 9
+ VERIZON_3G_4_BARS = 10
+ VERIZON_3G_3_BARS = 11
+ VERIZON_3G_2_BARS = 12
+ VERIZON_3G_1_BAR = 13
+ VERIZON_4G_1_BAR = 14
+ ATANDT_3G_5_BARS = 15
+ ATANDT_3G_4_BARS = 16
+ ATANDT_3G_3_BARS = 17
+ ATANDT_3G_2_BARS = 18
+ ATANDT_3G_1_BAR = 19
+ GENERIC_2G_4_BARS = 20
+ GENERIC_2G_3_BARS = 21
+ GENERIC_EVOLVED_EDGE = 22
+ GENERIC_GPRS = 23
+ GENERIC_ENHANCED_GPRS = 24
+ GENERIC_LTE = 25
+ GENERIC_HIGH_LATENCY_DNS = 26
+ GENERIC_100_PERCENT_PACKET_LOSS = 27
+ ATANDT_HSPA_PLUS = 28
+ ATANDT_4G_LTE_4_BARS = 29
+ VERIZON_4G_LTE_4_BARS = 30
+ GENERIC_DIGITAL_SUBSCRIBE_LINE = 31
+ WIFI_STARBUCKS_3_BARS = 32
+ WIFI_STARBUCKS_4_BARS = 33
+ WIFI_STARBUCKS_HIGH_TRAFFIC = 34
+ WIFI_TARGET_1_BAR = 35
+ WIFI_TARGET_3_BARS = 36
+ WIFI_TARGET_4_BARS = 37
+ PUBLIC_WIFI_MCDONALDS_5_BARS = 38
+ PUBLIC_WIFI_MCDONALDS_4_BARS = 39
+ PUBLIC_WIFI_MCDONALDS_2_BARS = 40
+ PUBLIC_WIFI_MCDONALDS_1_BAR = 41
+ PUBLIC_WIFI_KOHLS_5_BARS = 42
+ PUBLIC_WIFI_KOHLS_4_BARS = 43
+ PUBLIC_WIFI_KOHLS_2_BARS = 44
+ PUBLIC_WIFI_ATANDT_5_BARS = 45
+ PUBLIC_WIFI_ATANDT_4_BARS = 46
+ PUBLIC_WIFI_ATANDT_2_BARS = 47
+ PUBLIC_WIFI_ATANDT_1_BAR = 48
+ BOINGO = 49
\ No newline at end of file
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index 8875096..b69c7b2 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -73,6 +73,7 @@
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._network_config = device_json.get('network_config', None)
self._remote_device = device_json.get('remote_device', None)
self._remote_device_minimum_os = device_json.get(
'remote_device_minimum_os', None)
@@ -81,9 +82,7 @@
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]
+ self._timeouts.update(device_json.get('timeouts', {}))
def command_line_override(
file_value, cmd_line_value, desc, print_value=True):
@@ -107,6 +106,8 @@
self._device_oem, args.device_oem, 'device_oem')
self._device_type = command_line_override(
self._device_type, args.device_type, 'device_type')
+ self._network_config = command_line_override(
+ self._network_config, args.network_config, 'network_config')
self._remote_device = command_line_override(
self._remote_device, args.remote_device, 'remote_device')
self._remote_device_minimum_os = command_line_override(
@@ -325,6 +326,10 @@
return self._device['device_type_id']
@property
+ def network_config(self):
+ return self._network_config
+
+ @property
def only_output_failures(self):
# TODO(jbudorick): Remove this once b/18981674 is fixed.
return True
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 4a155ac..7aa91ae 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -14,6 +14,7 @@
from pylib import constants
from pylib.base import test_run
+from pylib.remote.device import appurify_constants
from pylib.remote.device import appurify_sanitized
from pylib.remote.device import remote_device_helper
from pylib.utils import zip_utils
@@ -230,7 +231,10 @@
self._test_id = self._UploadTestToDevice('robotium', test_path)
logging.info('Setting config: %s' % config)
- self._SetTestConfig('robotium', config)
+ appurify_configs = {}
+ if self._env.network_config:
+ appurify_configs['network'] = self._env.network_config
+ self._SetTestConfig('robotium', config, **appurify_configs)
def _UploadAppToDevice(self, app_path):
"""Upload app to device."""
@@ -259,21 +263,32 @@
'Unable to upload %s.' % test_path)
return upload_results.json()['response']['test_id']
- def _SetTestConfig(self, runner_type, body):
+ def _SetTestConfig(self, runner_type, runner_configs,
+ network=appurify_constants.NETWORK.WIFI_1_BAR,
+ pcap=0, profiler=0, videocapture=0):
"""Generates and uploads config file for test.
Args:
- extras: Extra arguments to set in the config file.
+ runner_configs: Configs specific to the runner you are using.
+ network: Config to specify the network environment the devices running
+ the tests will be in.
+ pcap: Option to set the recording the of network traffic from the device.
+ profiler: Option to set the recording of CPU, memory, and network
+ transfer usage in the tests.
+ videocapture: Option to set video capture during the tests.
+
"""
logging.info('Generating config file for test.')
with tempfile.TemporaryFile() as config:
config_data = [
- '[appurify]',
- 'pcap=0',
- 'profiler=0',
- 'videocapture=0',
- '[%s]' % runner_type
+ '[appurify]',
+ 'network=%s' % network,
+ 'pcap=%s' % pcap,
+ 'profiler=%s' % profiler,
+ 'videocapture=%s' % videocapture,
+ '[%s]' % runner_type
]
- config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems())
+ config_data.extend(
+ '%s=%s' % (k, v) for k, v in runner_configs.iteritems())
config.write(''.join('%s\n' % l for l in config_data))
config.flush()
config.seek(0)
@@ -282,4 +297,4 @@
config_response = appurify_sanitized.api.config_upload(
self._env.token, config, self._test_id)
remote_device_helper.TestHttpResponse(
- config_response, 'Unable to upload test config.')
+ config_response, 'Unable to upload test config.')
\ No newline at end of file
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py
index c34244e..65664e3 100644
--- a/build/android/pylib/results/json_results.py
+++ b/build/android/pylib/results/json_results.py
@@ -16,6 +16,38 @@
A results dict that mirrors the one generated by
base/test/launcher/test_results_tracker.cc:SaveSummaryAsJSON.
"""
+ # Example json output.
+ # {
+ # "global_tags": [],
+ # "all_tests": [
+ # "test1",
+ # "test2",
+ # ],
+ # "disabled_tests": [],
+ # "per_iteration_data": [
+ # {
+ # "test1": [
+ # {
+ # "status": "SUCCESS",
+ # "elapsed_time_ms": 1,
+ # "output_snippet": "",
+ # "output_snippet_base64": "",
+ # "losless_snippet": "",
+ # },
+ # ],
+ # "test2": [
+ # {
+ # "status": "FAILURE",
+ # "elapsed_time_ms": 12,
+ # "output_snippet": "",
+ # "output_snippet_base64": "",
+ # "losless_snippet": "",
+ # },
+ # ],
+ # },
+ # ],
+ # }
+
assert isinstance(test_run_result, base_test_result.TestRunResults)
def status_as_string(s):
@@ -71,3 +103,37 @@
with open(file_path, 'w') as json_result_file:
json_result_file.write(json.dumps(GenerateResultsDict(test_run_result)))
+
+def ParseResultsFromJson(json_results):
+ """Creates a list of BaseTestResult objects from JSON.
+
+ Args:
+ json_results: A JSON dict in the format created by
+ GenerateJsonResultsFile.
+ """
+
+ def string_as_status(s):
+ if s == 'SUCCESS':
+ return base_test_result.ResultType.PASS
+ elif s == 'SKIPPED':
+ return base_test_result.ResultType.SKIP
+ elif s == 'FAILURE':
+ return base_test_result.ResultType.FAIL
+ elif s == 'CRASH':
+ return base_test_result.ResultType.CRASH
+ elif s == 'TIMEOUT':
+ return base_test_result.ResultType.TIMEOUT
+ else:
+ return base_test_result.ResultType.UNKNOWN
+
+ results_list = []
+ testsuite_runs = json_results['per_iteration_data']
+ for testsuite_run in testsuite_runs:
+ for test, test_runs in testsuite_run.iteritems():
+ results_list.extend(
+ [base_test_result.BaseTestResult(test,
+ string_as_status(tr['status']),
+ duration=tr['elapsed_time_ms'])
+ for tr in test_runs])
+ return results_list
+
diff --git a/build/android/pylib/screenshot.py b/build/android/pylib/screenshot.py
index e21d756..0fcc590 100644
--- a/build/android/pylib/screenshot.py
+++ b/build/android/pylib/screenshot.py
@@ -2,11 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import logging
import os
-import signal
import tempfile
+import time
from pylib import cmd_helper
+from pylib import device_signal
+from pylib.device import device_errors
# TODO(jbudorick) Remove once telemetry gets switched over.
import pylib.android_commands
@@ -71,7 +74,9 @@
self._is_started = False
if not self._recorder:
return
- self._device.KillAll('screenrecord', signum=signal.SIGINT)
+ if not self._device.KillAll('screenrecord', signum=device_signal.SIGINT,
+ quiet=True):
+ logging.warning('Nothing to kill: screenrecord was not running')
self._recorder.wait()
def Pull(self, host_file=None):
@@ -82,10 +87,13 @@
Returns:
Output video file name on the host.
"""
- host_file_name = host_file or ('screen-recording-%s.mp4' %
- self._device.old_interface.GetTimestamp())
+ # TODO(jbudorick): Merge filename generation with the logic for doing so in
+ # DeviceUtils.
+ host_file_name = (
+ host_file
+ or 'screen-recording-%s.mp4' % time.strftime('%Y%m%dT%H%M%S',
+ time.localtime()))
host_file_name = os.path.abspath(host_file_name)
- self._device.old_interface.EnsureHostDirectory(host_file_name)
self._device.PullFile(self._device_file, host_file_name)
self._device.RunShellCommand('rm -f "%s"' % self._device_file)
return host_file_name
diff --git a/build/android/pylib/uiautomator/test_options.py b/build/android/pylib/uiautomator/test_options.py
index b383b20..3f5f950 100644
--- a/build/android/pylib/uiautomator/test_options.py
+++ b/build/android/pylib/uiautomator/test_options.py
@@ -8,7 +8,6 @@
UIAutomatorOptions = collections.namedtuple('UIAutomatorOptions', [
'tool',
- 'cleanup_test_files',
'annotations',
'exclude_annotations',
'test_filter',
diff --git a/build/android/pylib/uiautomator/test_runner.py b/build/android/pylib/uiautomator/test_runner.py
index d7a4bdf..296bd47 100644
--- a/build/android/pylib/uiautomator/test_runner.py
+++ b/build/android/pylib/uiautomator/test_runner.py
@@ -26,7 +26,6 @@
# Create an InstrumentationOptions object to pass to the super class
instrumentation_options = instr_test_options.InstrumentationOptions(
test_options.tool,
- test_options.cleanup_test_files,
test_options.annotations,
test_options.exclude_annotations,
test_options.test_filter,
diff --git a/build/android/pylib/utils/emulator.py b/build/android/pylib/utils/emulator.py
index 81b9c98..26b9109 100644
--- a/build/android/pylib/utils/emulator.py
+++ b/build/android/pylib/utils/emulator.py
@@ -19,6 +19,7 @@
from pylib import cmd_helper
from pylib import constants
from pylib import pexpect
+from pylib.device import device_errors
from pylib.device import device_utils
from pylib.utils import time_profile
@@ -394,33 +395,30 @@
"""
seconds_waited = 0
number_of_waits = 2 # Make sure we can wfd twice
- # TODO(jbudorick) Un-handroll this in the implementation switch.
- adb_cmd = "adb -s %s %s" % (self.device_serial, 'wait-for-device')
+
+ device = device_utils.DeviceUtils(self.device_serial)
while seconds_waited < self._LAUNCH_TIMEOUT:
try:
- run_command.RunCommand(adb_cmd,
- timeout_time=self._WAITFORDEVICE_TIMEOUT,
- retry_count=1)
+ device.adb.WaitForDevice(
+ timeout=self._WAITFORDEVICE_TIMEOUT, retries=1)
number_of_waits -= 1
if not number_of_waits:
break
- except errors.WaitForResponseTimedOutError:
+ except device_errors.CommandTimeoutError:
seconds_waited += self._WAITFORDEVICE_TIMEOUT
- adb_cmd = "adb -s %s %s" % (self.device_serial, 'kill-server')
- run_command.RunCommand(adb_cmd)
+ device.adb.KillServer()
self.popen.poll()
if self.popen.returncode != None:
raise EmulatorLaunchException('EMULATOR DIED')
+
if seconds_waited >= self._LAUNCH_TIMEOUT:
raise EmulatorLaunchException('TIMEOUT with wait-for-device')
+
logging.info('Seconds waited on wait-for-device: %d', seconds_waited)
if wait_for_boot:
# Now that we checked for obvious problems, wait for a boot complete.
# Waiting for the package manager is sometimes problematic.
- # TODO(jbudorick) Convert this once waiting for the package manager and
- # the external storage is no longer problematic.
- d = device_utils.DeviceUtils(self.device_serial)
- d.old_interface.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
+ device.WaitUntilFullyBooted(timeout=self._WAITFORBOOT_TIMEOUT)
def Shutdown(self):
"""Shuts down the process started by launch."""
diff --git a/build/android/pylib/utils/findbugs.py b/build/android/pylib/utils/findbugs.py
index 82408b0..8deb0fe 100644
--- a/build/android/pylib/utils/findbugs.py
+++ b/build/android/pylib/utils/findbugs.py
@@ -2,254 +2,153 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import optparse
+import argparse
+import logging
import os
import re
import shlex
-import subprocess
import sys
+import xml.dom.minidom
from pylib import cmd_helper
from pylib import constants
-def _PrintMessage(warnings, title, action, known_bugs_file):
- if warnings:
- print
- print '*' * 80
- print '%s warnings.' % title
- print '%s %s' % (action, known_bugs_file)
- print '-' * 80
- for warning in warnings:
- print warning
- print '-' * 80
- print
+_FINDBUGS_HOME = os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
+ 'findbugs')
+_FINDBUGS_JAR = os.path.join(_FINDBUGS_HOME, 'lib', 'findbugs.jar')
+_FINDBUGS_MAX_HEAP = 768
+_FINDBUGS_PLUGIN_PATH = os.path.join(
+ constants.DIR_SOURCE_ROOT, 'tools', 'android', 'findbugs_plugin', 'lib',
+ 'chromiumPlugin.jar')
-def _StripLineNumbers(current_warnings):
- re_line = r':\[line.*?\]$'
- return [re.sub(re_line, '', x) for x in current_warnings]
+def _ParseXmlResults(results_doc):
+ warnings = set()
+ for en in (n for n in results_doc.documentElement.childNodes
+ if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+ if en.tagName == 'BugInstance':
+ warnings.add(_ParseBugInstance(en))
+ return warnings
-def _DiffKnownWarnings(current_warnings_set, known_bugs_file):
- if os.path.exists(known_bugs_file):
- with open(known_bugs_file, 'r') as known_bugs:
- known_bugs_set = set(known_bugs.read().splitlines())
- else:
- known_bugs_set = set()
-
- new_warnings = current_warnings_set - known_bugs_set
- _PrintMessage(sorted(new_warnings), 'New', 'Please fix, or perhaps add to',
- known_bugs_file)
-
- obsolete_warnings = known_bugs_set - current_warnings_set
- _PrintMessage(sorted(obsolete_warnings), 'Obsolete', 'Please remove from',
- known_bugs_file)
-
- count = len(new_warnings) + len(obsolete_warnings)
- if count:
- print '*** %d FindBugs warning%s! ***' % (count, 's' * (count > 1))
- if len(new_warnings):
- print '*** %d: new ***' % len(new_warnings)
- if len(obsolete_warnings):
- print '*** %d: obsolete ***' % len(obsolete_warnings)
- print
- print 'Alternatively, rebaseline with --rebaseline command option'
- print
- else:
- print 'No new FindBugs warnings.'
- print
- return count
+def _GetMessage(node):
+ for c in (n for n in node.childNodes
+ if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+ if c.tagName == 'Message':
+ if (len(c.childNodes) == 1
+ and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+ return c.childNodes[0].data
+ return None
-def _Rebaseline(current_warnings_set, known_bugs_file):
- with file(known_bugs_file, 'w') as known_bugs:
- for warning in sorted(current_warnings_set):
- print >> known_bugs, warning
- return 0
+def _ParseBugInstance(node):
+ bug = FindBugsWarning(node.getAttribute('type'))
+ msg_parts = []
+ for c in (n for n in node.childNodes
+ if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+ if c.tagName == 'Class':
+ msg_parts.append(_GetMessage(c))
+ elif c.tagName == 'Method':
+ msg_parts.append(_GetMessage(c))
+ elif c.tagName == 'Field':
+ msg_parts.append(_GetMessage(c))
+ elif c.tagName == 'SourceLine':
+ bug.file_name = c.getAttribute('sourcefile')
+ if c.hasAttribute('start'):
+ bug.start_line = int(c.getAttribute('start'))
+ if c.hasAttribute('end'):
+ bug.end_line = int(c.getAttribute('end'))
+ msg_parts.append(_GetMessage(c))
+ elif (c.tagName == 'ShortMessage' and len(c.childNodes) == 1
+ and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+ msg_parts.append(c.childNodes[0].data)
+ bug.message = tuple(m for m in msg_parts if m)
+ return bug
-def _GetChromeJars(release_version):
- version = 'Debug'
- if release_version:
- version = 'Release'
- path = os.path.join(constants.DIR_SOURCE_ROOT,
- os.environ.get('CHROMIUM_OUT_DIR', 'out'),
- version,
- 'lib.java')
- cmd = 'find %s -name "*.jar"' % path
- out = cmd_helper.GetCmdOutput(shlex.split(cmd))
- out = [p for p in out.splitlines() if not p.endswith('.dex.jar')]
- if not out:
- print 'No classes found in %s' % path
- return ' '.join(out)
+class FindBugsWarning(object):
+
+ def __init__(self, bug_type='', end_line=0, file_name='', message=None,
+ start_line=0):
+ self.bug_type = bug_type
+ self.end_line = end_line
+ self.file_name = file_name
+ if message is None:
+ self.message = tuple()
+ else:
+ self.message = message
+ self.start_line = start_line
+
+ def __cmp__(self, other):
+ return (cmp(self.file_name, other.file_name)
+ or cmp(self.start_line, other.start_line)
+ or cmp(self.end_line, other.end_line)
+ or cmp(self.bug_type, other.bug_type)
+ or cmp(self.message, other.message))
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __hash__(self):
+ return hash((self.bug_type, self.end_line, self.file_name, self.message,
+ self.start_line))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __str__(self):
+ return '%s: %s' % (self.bug_type, '\n '.join(self.message))
-def _Run(exclude, known_bugs, classes_to_analyze, auxiliary_classes,
- rebaseline, release_version, findbug_args):
- """Run the FindBugs.
+def Run(exclude, classes_to_analyze, auxiliary_classes, output_file,
+ findbug_args, jars):
+ """Run FindBugs.
Args:
exclude: the exclude xml file, refer to FindBugs's -exclude command option.
- known_bugs: the text file of known bugs. The bugs in it will not be
- reported.
classes_to_analyze: the list of classes need to analyze, refer to FindBug's
-onlyAnalyze command line option.
auxiliary_classes: the classes help to analyze, refer to FindBug's
-auxclasspath command line option.
- rebaseline: True if the known_bugs file needs rebaseline.
- release_version: True if the release version needs check, otherwise check
- debug version.
- findbug_args: addtional command line options needs pass to Findbugs.
+ output_file: An optional path to dump XML results to.
+ findbug_args: A list of addtional command line options to pass to Findbugs.
"""
+ # TODO(jbudorick): Get this from the build system.
+ system_classes = [
+ os.path.join(constants.ANDROID_SDK_ROOT, 'platforms',
+ 'android-%s' % constants.ANDROID_SDK_VERSION, 'android.jar')
+ ]
+ system_classes.extend(os.path.abspath(classes)
+ for classes in auxiliary_classes or [])
- chrome_src = constants.DIR_SOURCE_ROOT
- sdk_root = constants.ANDROID_SDK_ROOT
- sdk_version = constants.ANDROID_SDK_VERSION
-
- system_classes = []
- system_classes.append(os.path.join(sdk_root, 'platforms',
- 'android-%s' % sdk_version, 'android.jar'))
- if auxiliary_classes:
- for classes in auxiliary_classes:
- system_classes.append(os.path.abspath(classes))
-
- findbugs_javacmd = 'java'
- findbugs_home = os.path.join(chrome_src, 'third_party', 'findbugs')
- findbugs_jar = os.path.join(findbugs_home, 'lib', 'findbugs.jar')
- findbugs_pathsep = ':'
- findbugs_maxheap = '768'
-
- cmd = '%s ' % findbugs_javacmd
- cmd = '%s -classpath %s%s' % (cmd, findbugs_jar, findbugs_pathsep)
- cmd = '%s -Xmx%sm ' % (cmd, findbugs_maxheap)
- cmd = '%s -Dfindbugs.home="%s" ' % (cmd, findbugs_home)
- cmd = '%s -jar %s ' % (cmd, findbugs_jar)
-
- cmd = '%s -textui -sortByClass ' % cmd
- cmd = '%s -pluginList %s' % (cmd, os.path.join(chrome_src, 'tools', 'android',
- 'findbugs_plugin', 'lib',
- 'chromiumPlugin.jar'))
- if len(system_classes):
- cmd = '%s -auxclasspath %s ' % (cmd, ':'.join(system_classes))
-
+ cmd = ['java',
+ '-classpath', '%s:' % _FINDBUGS_JAR,
+ '-Xmx%dm' % _FINDBUGS_MAX_HEAP,
+ '-Dfindbugs.home="%s"' % _FINDBUGS_HOME,
+ '-jar', _FINDBUGS_JAR,
+ '-textui', '-sortByClass',
+ '-pluginList', _FINDBUGS_PLUGIN_PATH, '-xml:withMessages']
+ if system_classes:
+ cmd.extend(['-auxclasspath', ':'.join(system_classes)])
if classes_to_analyze:
- cmd = '%s -onlyAnalyze %s ' % (cmd, classes_to_analyze)
-
+ cmd.extend(['-onlyAnalyze', classes_to_analyze])
if exclude:
- cmd = '%s -exclude %s ' % (cmd, os.path.abspath(exclude))
-
+ cmd.extend(['-exclude', os.path.abspath(exclude)])
+ if output_file:
+ cmd.extend(['-output', output_file])
if findbug_args:
- cmd = '%s %s ' % (cmd, findbug_args)
+ cmd.extend(findbug_args)
+ cmd.extend(os.path.abspath(j) for j in jars or [])
- chrome_classes = _GetChromeJars(release_version)
- if not chrome_classes:
- return 1
- cmd = '%s %s ' % (cmd, chrome_classes)
-
- print
- print '*' * 80
- print 'Command used to run findbugs:'
- print cmd
- print '*' * 80
- print
-
- proc = subprocess.Popen(shlex.split(cmd),
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, _err = proc.communicate()
- current_warnings_set = set(_StripLineNumbers(filter(None, out.splitlines())))
-
- if rebaseline:
- return _Rebaseline(current_warnings_set, known_bugs)
+ if output_file:
+ cmd_helper.RunCmd(cmd)
+ results_doc = xml.dom.minidom.parse(output_file)
else:
- return _DiffKnownWarnings(current_warnings_set, known_bugs)
+ raw_out = cmd_helper.GetCmdOutput(cmd)
+ results_doc = xml.dom.minidom.parseString(raw_out)
-def Run(options):
- exclude_file = None
- known_bugs_file = None
+ current_warnings_set = _ParseXmlResults(results_doc)
- if options.exclude:
- exclude_file = options.exclude
- elif options.base_dir:
- exclude_file = os.path.join(options.base_dir, 'findbugs_exclude.xml')
+ return (' '.join(cmd), current_warnings_set)
- if options.known_bugs:
- known_bugs_file = options.known_bugs
- elif options.base_dir:
- known_bugs_file = os.path.join(options.base_dir, 'findbugs_known_bugs.txt')
-
- auxclasspath = None
- if options.auxclasspath:
- auxclasspath = options.auxclasspath.split(':')
- return _Run(exclude_file, known_bugs_file, options.only_analyze, auxclasspath,
- options.rebaseline, options.release_build, options.findbug_args)
-
-
-def GetCommonParser():
- parser = optparse.OptionParser()
- parser.add_option('-r',
- '--rebaseline',
- action='store_true',
- dest='rebaseline',
- help='Rebaseline known findbugs issues.')
-
- parser.add_option('-a',
- '--auxclasspath',
- action='store',
- default=None,
- dest='auxclasspath',
- help='Set aux classpath for analysis.')
-
- parser.add_option('-o',
- '--only-analyze',
- action='store',
- default=None,
- dest='only_analyze',
- help='Only analyze the given classes and packages.')
-
- parser.add_option('-e',
- '--exclude',
- action='store',
- default=None,
- dest='exclude',
- help='Exclude bugs matching given filter.')
-
- parser.add_option('-k',
- '--known-bugs',
- action='store',
- default=None,
- dest='known_bugs',
- help='Not report the bugs in the given file.')
-
- parser.add_option('-l',
- '--release-build',
- action='store_true',
- dest='release_build',
- help='Analyze release build instead of debug.')
-
- parser.add_option('-f',
- '--findbug-args',
- action='store',
- default=None,
- dest='findbug_args',
- help='Additional findbug arguments.')
-
- parser.add_option('-b',
- '--base-dir',
- action='store',
- default=None,
- dest='base_dir',
- help='Base directory for configuration file.')
-
- return parser
-
-
-def main():
- parser = GetCommonParser()
- options, _ = parser.parse_args()
-
- return Run(options)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index fcbe427..90d5ca0 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -24,12 +24,16 @@
def DefaultConfigVariables():
+ # Note: This list must match the --config-vars in build/isolate.gypi
return {
'CONFIGURATION_NAME': constants.GetBuildType(),
'OS': 'android',
'asan': '0',
+ 'branding': 'Chromium',
'chromeos': '0',
'component': 'static_library',
+ 'enable_pepper_cdms': '0',
+ 'enable_plugins': '0',
'fastbuild': '0',
'icu_use_data_file_flag': '1',
'lsan': '0',
@@ -39,6 +43,7 @@
'tsan': '0',
'use_custom_libcxx': '0',
'use_instrumented_libraries': '0',
+ 'use_prebuilt_instrumented_libraries': '0',
'use_openssl': '0',
'use_ozone': '0',
'use_x11': '0',
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py
index da3cd15..4d7d0b0 100644
--- a/build/android/pylib/utils/md5sum.py
+++ b/build/android/pylib/utils/md5sum.py
@@ -5,6 +5,7 @@
import collections
import logging
import os
+import re
import tempfile
import types
@@ -12,8 +13,6 @@
from pylib import constants
from pylib.utils import device_temp_file
-HashAndPath = collections.namedtuple('HashAndPath', ['hash', 'path'])
-
MD5SUM_DEVICE_LIB_PATH = '/data/local/tmp/md5sum/'
MD5SUM_DEVICE_BIN_PATH = MD5SUM_DEVICE_LIB_PATH + 'md5sum_bin'
@@ -21,6 +20,8 @@
'test -f {path} -o -d {path} '
'&& LD_LIBRARY_PATH={md5sum_lib} {device_pie_wrapper} {md5sum_bin} {path}')
+_STARTS_WITH_CHECKSUM_RE = re.compile(r'^\s*[0-9a-fA-f]{32}\s+')
+
def CalculateHostMd5Sums(paths):
"""Calculates the MD5 sum value for all items in |paths|.
@@ -28,7 +29,7 @@
Args:
paths: A list of host paths to md5sum.
Returns:
- A list of named tuples with 'hash' and 'path' attributes.
+ A dict mapping paths to their respective md5sum checksums.
"""
if isinstance(paths, basestring):
paths = [paths]
@@ -36,7 +37,8 @@
out = cmd_helper.GetCmdOutput(
[os.path.join(constants.GetOutDirectory(), 'md5sum_bin_host')] +
[p for p in paths])
- return [HashAndPath(*l.split(None, 1)) for l in out.splitlines()]
+
+ return _ParseMd5SumOutput(out.splitlines())
def CalculateDeviceMd5Sums(paths, device):
@@ -45,7 +47,7 @@
Args:
paths: A list of device paths to md5sum.
Returns:
- A list of named tuples with 'hash' and 'path' attributes.
+ A dict mapping paths to their respective md5sum checksums.
"""
if isinstance(paths, basestring):
paths = [paths]
@@ -72,5 +74,11 @@
device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name)
out = device.RunShellCommand(['sh', md5sum_device_script_file.name])
- return [HashAndPath(*l.split(None, 1)) for l in out if l]
+ return _ParseMd5SumOutput(out)
+
+
+def _ParseMd5SumOutput(out):
+ hash_and_path = (l.split(None, 1) for l in out
+ if l and _STARTS_WITH_CHECKSUM_RE.match(l))
+ return dict((p, h) for h, p in hash_and_path)
diff --git a/build/android/pylib/utils/md5sum_test.py b/build/android/pylib/utils/md5sum_test.py
index 6c689fb..de9cd35 100755
--- a/build/android/pylib/utils/md5sum_test.py
+++ b/build/android/pylib/utils/md5sum_test.py
@@ -39,8 +39,9 @@
with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
out = md5sum.CalculateHostMd5Sums(test_path)
self.assertEquals(1, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/test/host/file.dat', out[0].path)
+ self.assertTrue('/test/host/file.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/test/host/file.dat'])
mock_get_cmd_output.assert_called_once_with(
[HOST_MD5_EXECUTABLE, '/test/host/file.dat'])
@@ -52,10 +53,12 @@
with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
out = md5sum.CalculateHostMd5Sums(test_paths)
self.assertEquals(2, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/test/host/file0.dat', out[0].path)
- self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
- self.assertEquals('/test/host/file1.dat', out[1].path)
+ self.assertTrue('/test/host/file0.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/test/host/file0.dat'])
+ self.assertTrue('/test/host/file1.dat' in out)
+ self.assertEquals('123456789abcdef00fedcba987654321',
+ out['/test/host/file1.dat'])
mock_get_cmd_output.assert_called_once_with(
[HOST_MD5_EXECUTABLE, '/test/host/file0.dat',
'/test/host/file1.dat'])
@@ -68,10 +71,12 @@
with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
out = md5sum.CalculateHostMd5Sums(test_paths)
self.assertEquals(2, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/test/host/file0.dat', out[0].path)
- self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
- self.assertEquals('/test/host/file1.dat', out[1].path)
+ self.assertTrue('/test/host/file0.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/test/host/file0.dat'])
+ self.assertTrue('/test/host/file1.dat' in out)
+ self.assertEquals('123456789abcdef00fedcba987654321',
+ out['/test/host/file1.dat'])
mock_get_cmd_output.assert_called_once_with(
[HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat'])
@@ -99,8 +104,9 @@
new=mock_device_temp_file)):
out = md5sum.CalculateDeviceMd5Sums(test_path, device)
self.assertEquals(1, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/storage/emulated/legacy/test/file.dat', out[0].path)
+ self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/storage/emulated/legacy/test/file.dat'])
device.adb.Push.assert_called_once_with(
'/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
device.RunShellCommand.assert_called_once_with(
@@ -132,10 +138,12 @@
new=mock_device_temp_file)):
out = md5sum.CalculateDeviceMd5Sums(test_path, device)
self.assertEquals(2, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
- self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
- self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+ self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/storage/emulated/legacy/test/file0.dat'])
+ self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+ self.assertEquals('123456789abcdef00fedcba987654321',
+ out['/storage/emulated/legacy/test/file1.dat'])
device.adb.Push.assert_called_once_with(
'/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
device.RunShellCommand.assert_called_once_with(
@@ -168,10 +176,47 @@
new=mock_device_temp_file)):
out = md5sum.CalculateDeviceMd5Sums(test_path, device)
self.assertEquals(2, len(out))
- self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
- self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
- self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
- self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+ self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/storage/emulated/legacy/test/file0.dat'])
+ self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+ self.assertEquals('123456789abcdef00fedcba987654321',
+ out['/storage/emulated/legacy/test/file1.dat'])
+ device.adb.Push.assert_called_once_with(
+ '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+ device.RunShellCommand.assert_called_once_with(
+ ['sh', '/data/local/tmp/test/script/file.sh'])
+
+ def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self):
+ # See crbug/479966
+ test_path = '/storage/emulated/legacy/test/file.dat'
+
+ device = mock.NonCallableMock()
+ device.adb = mock.NonCallableMock()
+ device.adb.Push = mock.Mock()
+ device_md5sum_output = [
+ 'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: '
+ 'unused DT entry: type 0x1d arg 0x15db',
+ '0123456789abcdeffedcba9876543210 '
+ '/storage/emulated/legacy/test/file.dat',
+ ]
+ device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+ mock_temp_file = mock.mock_open()
+ mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+ mock_device_temp_file = mock.mock_open()
+ mock_device_temp_file.return_value.name = (
+ '/data/local/tmp/test/script/file.sh')
+
+ with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+ mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+ new=mock_device_temp_file)):
+ out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+ self.assertEquals(1, len(out))
+ self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+ self.assertEquals('0123456789abcdeffedcba9876543210',
+ out['/storage/emulated/legacy/test/file.dat'])
device.adb.Push.assert_called_once_with(
'/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
device.RunShellCommand.assert_called_once_with(
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py
index 3052b0d..59167ba 100644
--- a/build/android/pylib/utils/mock_calls.py
+++ b/build/android/pylib/utils/mock_calls.py
@@ -36,7 +36,7 @@
expected_call, action = self._expected_calls.pop(0)
self._test_case.assertTrue(
received_call == expected_call,
- msg=('Expected call missmatch:\n'
+ msg=('Expected call mismatch:\n'
' expected: %s\n'
' received: %s\n'
% (str(expected_call), str(received_call))))
diff --git a/build/android/pylib/utils/test_environment.py b/build/android/pylib/utils/test_environment.py
index 4d88a45..e78eb5c 100644
--- a/build/android/pylib/utils/test_environment.py
+++ b/build/android/pylib/utils/test_environment.py
@@ -34,13 +34,14 @@
"""Clean up the test environment, restarting fresh adb and HTTP daemons."""
_KillWebServers()
device_utils.RestartServer()
- p = device_utils.DeviceUtils.parallel()
- p.old_interface.RestartAdbdOnDevice()
- try:
- p.EnableRoot()
- except device_errors.CommandFailedError as e:
- # TODO(jbudorick) Handle this exception appropriately after interface
- # conversions are finished.
- logging.error(str(e))
- p.WaitUntilFullyBooted()
+
+ def cleanup_device(d):
+ d.old_interface.RestartAdbdOnDevice()
+ try:
+ d.EnableRoot()
+ except device_errors.CommandFailedError as e:
+ logging.error(str(e))
+ d.WaitUntilFullyBooted()
+
+ device_utils.DeviceUtils.parallel().pMap(cleanup_device)
diff --git a/build/android/screenshot.py b/build/android/screenshot.py
index 8fe2a95..c48a255 100755
--- a/build/android/screenshot.py
+++ b/build/android/screenshot.py
@@ -11,8 +11,8 @@
import os
import sys
-from pylib import android_commands
from pylib import screenshot
+from pylib.device import device_errors
from pylib.device import device_utils
def _PrintMessage(heading, eol='\n'):
@@ -66,21 +66,25 @@
(options, args) = parser.parse_args()
- if options.verbose:
- logging.getLogger().setLevel(logging.DEBUG)
-
- devices = android_commands.GetAttachedDevices()
-
- if not options.device and len(devices) > 1:
- parser.error('Multiple devices are attached. '
- 'Please specify device serial number with --device.')
- elif not options.device and len(devices) == 1:
- options.device = devices[0]
-
if len(args) > 1:
parser.error('Too many positional arguments.')
host_file = args[0] if args else options.file
- device = device_utils.DeviceUtils(options.device)
+
+ if options.verbose:
+ logging.getLogger().setLevel(logging.DEBUG)
+
+ devices = device_utils.DeviceUtils.HealthyDevices()
+
+ if not options.device:
+ if len(devices) > 1:
+ parser.error('Multiple devices are attached. '
+ 'Please specify device serial number with --device.')
+ elif len(devices) == 1:
+ device = devices[0]
+ else:
+ raise device_errors.NoDevicesError()
+ else:
+ device = device_utils.DeviceUtils(options.device)
if options.video:
_CaptureVideo(device, host_file, options)
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 368ac06..c54ed28 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -152,6 +152,9 @@
'Overrides all other flags.'))
group.add_argument('--remote-device-timeout', type=int,
help='Times to retry finding remote device')
+ group.add_argument('--network-config', type=int,
+ help='Integer that specifies the network environment '
+ 'that the tests will be run in.')
device_os_group = group.add_mutually_exclusive_group()
device_os_group.add_argument('--remote-device-minimum-os',
@@ -175,9 +178,6 @@
def AddDeviceOptions(parser):
"""Adds device options to |parser|."""
group = parser.add_argument_group(title='Device Options')
- group.add_argument('-c', dest='cleanup_test_files',
- help='Cleanup test files on the device after run',
- action='store_true')
group.add_argument('--tool',
dest='tool',
help=('Run the test under a tool '
@@ -372,7 +372,6 @@
# TODO(jbudorick): Get rid of InstrumentationOptions.
return instrumentation_test_options.InstrumentationOptions(
args.tool,
- args.cleanup_test_files,
args.annotations,
args.exclude_annotations,
args.test_filter,
@@ -437,7 +436,6 @@
return uiautomator_test_options.UIAutomatorOptions(
args.tool,
- args.cleanup_test_files,
args.annotations,
args.exclude_annotations,
args.test_filter,
@@ -636,7 +634,6 @@
# into the gtest code.
gtest_options = gtest_test_options.GTestOptions(
args.tool,
- args.cleanup_test_files,
args.test_filter,
args.run_disabled,
args.test_arguments,
@@ -768,7 +765,16 @@
def _RunJUnitTests(args):
"""Subcommand of RunTestsCommand which runs junit tests."""
runner_factory, tests = junit_setup.Setup(args)
- _, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+ results, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+
+ report_results.LogFull(
+ results=results,
+ test_type='JUnit',
+ test_package=args.test_suite)
+
+ if args.json_results_file:
+ json_results.GenerateJsonResultsFile(results, args.json_results_file)
+
return exit_code
diff --git a/build/android/tombstones.py b/build/android/tombstones.py
index 1a958ac..c83a584 100755
--- a/build/android/tombstones.py
+++ b/build/android/tombstones.py
@@ -19,7 +19,7 @@
import sys
import optparse
-from pylib import android_commands
+from pylib.device import adb_wrapper
from pylib.device import device_errors
from pylib.device import device_utils
from pylib.utils import run_tests_helper
@@ -233,19 +233,19 @@
options, _ = parser.parse_args()
if options.device:
- devices = [options.device]
+ devices = [device_utils.DeviceUtils(options.device)]
else:
- devices = android_commands.GetAttachedDevices()
+ devices = device_utils.DeviceUtils.HealthyDevices()
# This must be done serially because strptime can hit a race condition if
# used for the first time in a multithreaded environment.
# http://bugs.python.org/issue7980
tombstones = []
- for device_serial in devices:
- device = device_utils.DeviceUtils(device_serial)
+ for device in devices:
tombstones += _GetTombstonesForDevice(device, options)
_ResolveTombstones(options.jobs, tombstones)
+
if __name__ == '__main__':
sys.exit(main())
diff --git a/build/android/update_verification.py b/build/android/update_verification.py
index fe89567..45c6e98 100755
--- a/build/android/update_verification.py
+++ b/build/android/update_verification.py
@@ -12,12 +12,11 @@
import sys
import time
-from pylib import android_commands
from pylib.device import device_utils
def _SaveAppData(device, package_name, from_apk=None, data_dir=None):
def _BackupAppData(data_dir=None):
- device.old_interface.Adb().SendCommand('backup %s' % package_name)
+ device.adb.Backup(package_name)
backup_file = os.path.join(os.getcwd(), 'backup.ab')
assert os.path.exists(backup_file), 'Backup failed.'
if data_dir:
@@ -29,8 +28,7 @@
if from_apk:
logging.info('Installing %s...', from_apk)
- # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
- output = device.old_interface.Install(from_apk, reinstall=True)
+ output = device.Install(from_apk, reinstall=True)
if 'Success' not in output:
raise Exception('Unable to install %s. output: %s' % (from_apk, output))
@@ -42,14 +40,13 @@
def _VerifyAppUpdate(device, to_apk, app_data, from_apk=None):
def _RestoreAppData():
assert os.path.exists(app_data), 'Backup file does not exist!'
- device.old_interface.Adb().SendCommand('restore %s' % app_data)
+ device.adb.Restore(app_data)
# It seems restore command is not synchronous.
time.sleep(15)
if from_apk:
logging.info('Installing %s...', from_apk)
- # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
- output = device.old_interface.Install(from_apk, reinstall=True)
+ output = device.Install(from_apk, reinstall=True)
if 'Success' not in output:
raise Exception('Unable to install %s. output: %s' % (from_apk, output))
@@ -59,8 +56,7 @@
logging.info('Verifying that %s cannot be installed side-by-side...',
to_apk)
- # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
- output = device.old_interface.Install(to_apk)
+ output = device.Install(to_apk)
if 'INSTALL_FAILED_ALREADY_EXISTS' not in output:
if 'Success' in output:
raise Exception('Package name has changed! output: %s' % output)
@@ -68,8 +64,7 @@
raise Exception(output)
logging.info('Verifying that %s can be overinstalled...', to_apk)
- # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
- output = device.old_interface.Install(to_apk, reinstall=True)
+ output = device.adb.Install(to_apk, reinstall=True)
if 'Success' not in output:
raise Exception('Unable to install %s.\n output: %s' % (to_apk, output))
logging.info('Successfully updated to the new apk. Please verify that the '
@@ -112,10 +107,10 @@
parser.print_help(sys.stderr)
parser.error('Unknown arguments: %s.' % args)
- devices = android_commands.GetAttachedDevices()
+ devices = device_utils.DeviceUtils.HealthyDevices()
if len(devices) != 1:
parser.error('Exactly 1 device must be attached.')
- device = device_utils.DeviceUtils(devices[0])
+ device = devices[0]
if options.from_apk:
assert os.path.isfile(options.from_apk)
diff --git a/build/apk_test.gypi b/build/apk_test.gypi
index 05bafab..792d92c 100644
--- a/build/apk_test.gypi
+++ b/build/apk_test.gypi
@@ -31,7 +31,7 @@
'apk_name': '<(test_suite_name)',
'intermediate_dir': '<(PRODUCT_DIR)/<(test_suite_name)_apk',
'final_apk_path': '<(intermediate_dir)/<(test_suite_name)-debug.apk',
- 'java_in_dir': '<(DEPTH)/testing/android/java',
+ 'java_in_dir': '<(DEPTH)/testing/android/native_test/java',
'native_lib_target': 'lib<(test_suite_name)',
# TODO(yfriedman, cjhopman): Support managed installs for gtests.
'gyp_managed_install': 0,
diff --git a/build/build_config.h b/build/build_config.h
index b07660d..d8c3db6 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -61,8 +61,8 @@
#error Please add support for your platform in build/build_config.h
#endif
-#if defined(USE_OPENSSL) && defined(USE_NSS)
-#error Cannot use both OpenSSL and NSS
+#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS)
+#error Cannot use both OpenSSL and NSS for certificates
#endif
// For access to standard BSD features, use OS_BSD instead of a
diff --git a/build/common.gypi b/build/common.gypi
index e900cc4..c5a8fac 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -70,7 +70,10 @@
# certificates, use_openssl_certs must be set.
'use_openssl%': 0,
- # Typedef X509Certificate::OSCertHandle to OpenSSL's struct X509*.
+ # Use OpenSSL for representing certificates. When targeting Android,
+ # the platform certificate library is used for certificate
+ # verification. On other targets, this flag also enables OpenSSL for
+ # certificate verification, but this configuration is unsupported.
'use_openssl_certs%': 0,
# Disable viewport meta tag by default.
@@ -146,6 +149,7 @@
'enable_hidpi%': '<(enable_hidpi)',
'buildtype%': '<(buildtype)',
'branding%': '<(branding)',
+ 'branding_path_component%': '<(branding)',
'host_arch%': '<(host_arch)',
'target_arch%': '<(target_arch)',
@@ -155,12 +159,6 @@
# default. "default" should be used on non-official builds.
'android_channel%': 'default',
- # This is set when building the Android WebView inside the Android
- # build system, using the 'android' gyp backend. The WebView code is
- # still built when this is unset, but builds using the normal chromium
- # build system.
- 'android_webview_build%': 0,
-
# Set ARM architecture version.
'arm_version%': 7,
@@ -191,6 +189,14 @@
'mips_dsp_rev%': 0,
'conditions': [
+ ['branding == "Chrome"', {
+ 'branding_path_component%': 'google_chrome',
+ }],
+
+ ['branding == "Chromium"', {
+ 'branding_path_component%': 'chromium',
+ }],
+
# Ash needs Aura.
['use_aura==0', {
'use_ash%': 0,
@@ -248,14 +254,8 @@
# Set the default "target_subarch" on iOS. Valid values are "arm32",
# "arm64" and "both" (meaning a fat binary).
- #
- # TODO(sdefresne): change the default from "arm32" to "both" for
- # "target_subarch" once http://crbug.com/339477 is fixed.
- #
- # TODO(sdefresne): set the "target_arch" to "arm" once compilation
- # of skia has been fixed for simulator. http://crbug.com/342377
['OS=="ios"', {
- 'target_subarch%': 'arm32',
+ 'target_subarch%': 'arm64',
}],
# Set arch variants for MIPS platforms.
@@ -298,13 +298,13 @@
'enable_viewport%': '<(enable_viewport)',
'enable_hidpi%': '<(enable_hidpi)',
'android_channel%': '<(android_channel)',
- 'android_webview_build%': '<(android_webview_build)',
'use_goma%': '<(use_goma)',
'gomadir%': '<(gomadir)',
'enable_app_list%': '<(enable_app_list)',
'use_default_render_theme%': '<(use_default_render_theme)',
'buildtype%': '<(buildtype)',
'branding%': '<(branding)',
+ 'branding_path_component%': '<(branding_path_component)',
'arm_version%': '<(arm_version)',
'sysroot%': '<(sysroot)',
'chroot_cmd%': '<(chroot_cmd)',
@@ -633,14 +633,23 @@
# compiler. Always do this by default.
'host_clang%': 1,
- # Variables to control Link-Time Optimizations (LTO).
- # Note: the variables must *not* be enabled at the same time.
- # In this case LTO would 'merge' the optimization flags
- # at link-time which would lead to all code be optimized with -O2.
- # Enable LTO on the code compiled with -Os.
- # See crbug.com/407544
+ # Variables to control Link-Time Optimization (LTO).
+ # On Android, the variable use_lto enables LTO on code compiled with -Os,
+ # and use_lto_o2 enables LTO on code compiled with -O2. On other
+ # platforms, use_lto enables LTO in all translation units, and use_lto_o2
+ # has no effect.
+ #
+ # On Linux and Android, when using LLVM LTO, the script
+ # build/download_gold_plugin.py must be run to download a linker plugin.
+ # On Mac, LLVM needs to be built from scratch using
+ # tools/clang/scripts/update.py and the absolute path to
+ # third_party/llvm-build/Release+Asserts/lib must be added to
+ # $DYLD_LIBRARY_PATH to pick up the right version of the linker plugin.
+ #
+ # On Android, the variables must *not* be enabled at the same time.
+ # In this case LTO would 'merge' the optimization flags at link-time
+ # which would lead to all code be optimized with -O2. See crbug.com/407544
'use_lto%': 0,
- # Enable LTO on code compiled with -O2.
'use_lto_o2%': 0,
# Allowed level of identical code folding in the gold linker.
@@ -653,9 +662,22 @@
# See http://clang.llvm.org/docs/ControlFlowIntegrity.html
'cfi_vptr%': 0,
+ # Control Flow Integrity for casts.
+ # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+ 'cfi_derived_cast%': 0,
+ 'cfi_unrelated_cast%': 0,
+
+ 'cfi_blacklist%': '<(PRODUCT_DIR)/../../tools/cfi/blacklist.txt',
+
# Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
'mac_views_browser%': 0,
+ # By default, use ICU data file (icudtl.dat).
+ 'icu_use_data_file_flag%': 1,
+
+ # Turn on JNI generation optimizations by default.
+ 'optimize_jni_generation%': 1,
+
'conditions': [
# A flag for POSIX platforms
['OS=="win"', {
@@ -672,18 +694,10 @@
}],
# NSS usage.
- ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==0', {
- 'use_nss%': 1,
+ ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris")', {
+ 'use_nss_certs%': 1,
}, {
- 'use_nss%': 0,
- }],
-
- # When OpenSSL is used for SSL and crypto on Unix-like systems, use
- # OpenSSL's certificate definition.
- ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==1', {
- 'use_openssl_certs%': 1,
- }, {
- 'use_openssl_certs%': 0,
+ 'use_nss_certs%': 0,
}],
# libudev usage. This currently only affects the content layer.
@@ -786,8 +800,8 @@
'native_memory_pressure_signals%': 1,
}],
- # Enable autofill dialog for Android, Mac and Views-enabled platforms.
- ['toolkit_views==1 or (OS=="android" and android_webview_build==0) or OS=="mac"', {
+ # Enable autofill dialog when not on iOS.
+ ['OS!="ios"', {
'enable_autofill_dialog%': 1,
'conditions': [
@@ -852,7 +866,7 @@
# are using a custom toolchain and need to control -B in ldflags.
# Do not use 32-bit gold on 32-bit hosts as it runs out address space
# for component=static_library builds.
- ['OS=="linux" and (target_arch=="x64" or target_arch=="arm")', {
+ ['(OS=="linux" or OS=="android") and (target_arch=="x64" or target_arch=="arm")', {
'linux_use_bundled_gold%': 1,
}, {
'linux_use_bundled_gold%': 0,
@@ -901,7 +915,7 @@
#
# On Aura, this allows per-tile painting to be used in the browser
# compositor.
- ['OS!="android"', {
+ ['OS!="android" and OS!="ios"', {
'use_canvas_skia%': 1,
}],
@@ -986,15 +1000,6 @@
'enable_print_preview%': 0,
}],
- # By default, use ICU data file (icudtl.dat) on all platforms
- # except when building Android WebView.
- # TODO(jshin): Handle 'use_system_icu' on Linux (Chromium).
- # Set the data reduction proxy origin for Android Webview.
- ['android_webview_build==0', {
- 'icu_use_data_file_flag%' : 1,
- }, {
- 'icu_use_data_file_flag%' : 0,
- }],
['OS=="win" or OS=="mac"', {
'enable_wifi_bootstrapping%' : 1,
}],
@@ -1006,23 +1011,12 @@
}, {
'sas_dll_path%': '<(DEPTH)/third_party/platformsdk_win7/files/redist/x86',
}],
-
- # Turn on JNI generation optimizations on non-WebView builds.
- ['OS=="android" and android_webview_build==0', {
- 'optimize_jni_generation%': 1,
- }, {
- 'optimize_jni_generation%': 0,
- }],
-
- # TODO(rmcilroy): Enable v8_use_external_startup_data on ChromeOS
- # http://crbug.com/421063
- ['android_webview_build==0 and chromecast==0 and chromeos==0 and OS!="ios"', {
- 'v8_use_external_startup_data%': 1,
- }, {
- 'v8_use_external_startup_data%': 0,
- }],
],
+ # Setting this to '0' will cause V8's startup snapshot to be
+ # embedded in the binary instead of being a external files.
+ 'v8_use_external_startup_data%': 1,
+
# Set this to 1 to enable use of concatenated impulse responses
# for the HRTF panner in WebAudio.
'use_concatenated_impulse_responses': 1,
@@ -1073,10 +1067,16 @@
'google_default_client_secret%': '',
# Native Client is enabled by default.
'disable_nacl%': '0',
+
+ # Sets the default version name and code for Android app, by default we
+ # do a developer build.
+ 'android_app_version_name%': 'Developer Build',
+ 'android_app_version_code%': 1,
},
# Copy conditionally-set variables out one scope.
'branding%': '<(branding)',
+ 'branding_path_component%': '<(branding_path_component)',
'buildtype%': '<(buildtype)',
'target_arch%': '<(target_arch)',
'target_subarch%': '<(target_subarch)',
@@ -1091,7 +1091,7 @@
'use_libpci%': '<(use_libpci)',
'use_openssl%': '<(use_openssl)',
'use_openssl_certs%': '<(use_openssl_certs)',
- 'use_nss%': '<(use_nss)',
+ 'use_nss_certs%': '<(use_nss_certs)',
'use_udev%': '<(use_udev)',
'os_bsd%': '<(os_bsd)',
'os_posix%': '<(os_posix)',
@@ -1196,7 +1196,6 @@
'use_libjpeg_turbo%': '<(use_libjpeg_turbo)',
'use_system_libjpeg%': '<(use_system_libjpeg)',
'android_channel%': '<(android_channel)',
- 'android_webview_build%': '<(android_webview_build)',
'icu_use_data_file_flag%': '<(icu_use_data_file_flag)',
'gyp_managed_install%': 0,
'create_standalone_apk%': 1,
@@ -1224,7 +1223,12 @@
'video_hole%': '<(video_hole)',
'v8_use_external_startup_data%': '<(v8_use_external_startup_data)',
'cfi_vptr%': '<(cfi_vptr)',
+ 'cfi_derived_cast%': '<(cfi_derived_cast)',
+ 'cfi_unrelated_cast%': '<(cfi_unrelated_cast)',
+ 'cfi_blacklist%': '<(cfi_blacklist)',
'mac_views_browser%': '<(mac_views_browser)',
+ 'android_app_version_name%': '<(android_app_version_name)',
+ 'android_app_version_code%': '<(android_app_version_code)',
# Use system protobuf instead of bundled one.
'use_system_protobuf%': 0,
@@ -1417,7 +1421,7 @@
# Pseudo locales are special locales which are used for testing and
# debugging. They don't get copied to the final app. For more info,
- # check out https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
+ # check out https://www.chromium.org/developers/testing/fake-bidi
'pseudo_locales': [
'fake-bidi',
],
@@ -1456,11 +1460,6 @@
# we can build a debug version with acceptable size and performance.
'android_full_debug%': 0,
- # Sets the default version name and code for Android app, by default we
- # do a developer build.
- 'android_app_version_name%': 'Developer Build',
- 'android_app_version_code%': 1,
-
# Contains data about the attached devices for gyp_managed_install.
'build_device_config_path': '<(PRODUCT_DIR)/build_devices.cfg',
@@ -1503,6 +1502,7 @@
# Ozone platforms to include in the build.
'ozone_platform_caca%': 0,
+ 'ozone_platform_cast%': 0,
'ozone_platform_dri%': 0,
'ozone_platform_drm%': 0,
'ozone_platform_egltest%': 0,
@@ -1564,18 +1564,11 @@
# it takes effect here.
['os_posix==1 and OS!="mac" and OS!="ios" and clang==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan_vptr==0', {
'conditions': [
- ['OS=="android" and android_webview_build==0', {
+ ['OS=="android"', {
'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
# We directly set the gcc version since we know what we use.
'gcc_version%': 49,
- }],
- ['OS=="android" and android_webview_build==1', {
- # Android WebView uses a hermetic clang toolchain for host builds.
- 'host_gcc_version%': 0,
- # Android WebView uses the GCC toolchain from the Android build.
- 'gcc_version%': 48,
- }],
- ['OS!="android"', {
+ }, {
'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
'gcc_version%': '<!pymod_do_main(compiler_version target compiler)',
}],
@@ -1817,13 +1810,6 @@
# Uses system APIs for decoding audio and video.
'use_libffmpeg%': '0',
-
- # TODO(torne): Remove this unsupported option once all the places that
- # test it have been updated.
- 'use_system_stlport%': 0,
-
- # Copy it out one scope.
- 'android_webview_build%': '<(android_webview_build)',
}], # OS=="android"
['embedded==1', {
'use_system_fontconfig%': 0,
@@ -1844,10 +1830,8 @@
}],
],
}],
- ['android_webview_build==1', {
- # When building the WebView in the Android tree, jarjar will remap all
- # the class names, so the JNI generator needs to know this.
- 'jni_generator_jarjar_file': '../android_webview/build/jarjar-rules.txt',
+ ['chromecast==1 and OS!="android"', {
+ 'ozone_platform_cast%': 1
}],
['OS=="linux" and target_arch!="mipsel"', {
'clang%': 1,
@@ -2052,8 +2036,8 @@
['use_ash==1', {
'grit_defines': ['-D', 'use_ash'],
}],
- ['use_nss==1', {
- 'grit_defines': ['-D', 'use_nss'],
+ ['use_nss_certs==1', {
+ 'grit_defines': ['-D', 'use_nss_certs'],
}],
['use_ozone==1', {
'grit_defines': ['-D', 'use_ozone'],
@@ -2080,11 +2064,6 @@
'-E', 'ANDROID_JAVA_TAGGED_ONLY=true',
'--no-output-all-resource-defines',
],
- 'conditions': [
- ['<(android_webview_build)==1', {
- 'grit_defines': ['-D', 'is_android_webview_build'],
- }],
- ],
}],
['OS=="mac" or OS=="ios"', {
'grit_defines': ['-D', 'scale_factors=2x'],
@@ -2175,20 +2154,31 @@
'grit_defines': ['-D', 'enable_service_discovery'],
'enable_service_discovery%': 1
}],
- ['clang_use_chrome_plugins==1 and OS!="win"', {
+ ['clang_use_chrome_plugins==1', {
'variables': {
'conditions': [
- ['OS=="mac" or OS=="ios"', {
- 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
- }, { # OS != "mac" or OS != "ios"
- 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
- }],
+ ['OS!="win"', {
+ 'variables': {
+ 'conditions': [
+ ['OS=="mac" or OS=="ios"', {
+ 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
+ }, { # OS != "mac" or OS != "ios"
+ 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
+ }],
+ ],
+ },
+ 'clang_dynlib_flags%': '-Xclang -load -Xclang <(clang_lib_path) ',
+ }, { # OS == "win"
+ # On Windows, the plugin is built directly into clang, so there's
+ # no need to load it dynamically.
+ 'clang_dynlib_flags%': '',
+ }]
],
},
# If you change these, also change build/config/clang/BUILD.gn.
'clang_chrome_plugins_flags%':
- '-Xclang -load -Xclang <(clang_lib_path)'
- ' -Xclang -add-plugin -Xclang find-bad-constructs',
+ '<(clang_dynlib_flags)'
+ '-Xclang -add-plugin -Xclang find-bad-constructs',
}],
['asan==1 or msan==1 or lsan==1 or tsan==1', {
'clang%': 1,
@@ -2241,9 +2231,9 @@
}],
['OS=="win"', {
- # The Clang plugins don't currently work on Windows.
+ # The Blink GC plugin doesn't currently work on Windows.
# TODO(hans): One day, this will work. (crbug.com/82385)
- 'clang_use_chrome_plugins%': 0,
+ 'blink_gc_plugin%': 0,
}],
# On valgrind bots, override the optimizer settings so we don't inline too
@@ -2305,14 +2295,14 @@
}],
# Set default compiler flags depending on ARM version.
- ['arm_version==6 and android_webview_build==0', {
+ ['arm_version==6', {
'arm_arch%': 'armv6',
'arm_tune%': '',
'arm_fpu%': 'vfp',
'arm_float_abi%': 'softfp',
'arm_thumb%': 0,
}],
- ['arm_version==7 and android_webview_build==0', {
+ ['arm_version==7', {
'arm_arch%': 'armv7-a',
'arm_tune%': 'generic-armv7-a',
'conditions': [
@@ -2328,24 +2318,13 @@
}],
# Set default compiler flags for MIPS floating-point support.
- ['target_arch=="mipsel" and android_webview_build==0', {
+ ['target_arch=="mipsel"', {
'mips_float_abi%': 'hard',
}],
- ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
+ ['target_arch=="mipsel" and mips_arch_variant=="r2"', {
'mips_fpu_mode%': 'fp32',
}],
- ['android_webview_build==1', {
- # The WebView build gets its cpu-specific flags from the Android build system.
- 'arm_arch%': '',
- 'arm_tune%': '',
- 'arm_fpu%': '',
- 'arm_float_abi%': '',
- 'arm_thumb%': 0,
- 'mips_float_abi%': '',
- 'mips_fpu_mode%': '',
- }],
-
# Enable brlapi by default for chromeos.
[ 'chromeos==1', {
'use_brlapi%': 1,
@@ -2403,7 +2382,7 @@
'use_seccomp_bpf%': 0,
}],
- ['cfi_vptr==1', {
+ ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
'use_lto%': 1,
}],
],
@@ -2702,6 +2681,9 @@
['enable_webrtc==1', {
'defines': ['ENABLE_WEBRTC=1'],
}],
+ ['enable_media_router==1', {
+ 'defines': ['ENABLE_MEDIA_ROUTER=1'],
+ }],
['proprietary_codecs==1', {
'defines': ['USE_PROPRIETARY_CODECS'],
'conditions': [
@@ -3012,6 +2994,27 @@
['v8_use_external_startup_data==1', {
'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'],
}],
+
+ # SAFE_BROWSING_SERVICE - browser manages a safe-browsing service.
+ # SAFE_BROWSING_DB_LOCAL - service manages a local database.
+ # SAFE_BROWSING_DB_REMOTE - service talks via API to a database
+ # SAFE_BROWSING_CSD - enable client-side phishing detection.
+ ['safe_browsing==1', {
+ # TODO(nparker): Remove existing uses of FULL_SAFE_BROWSING
+ 'defines': [
+ 'FULL_SAFE_BROWSING',
+ 'SAFE_BROWSING_CSD',
+ 'SAFE_BROWSING_DB_LOCAL',
+ 'SAFE_BROWSING_SERVICE',
+ ],
+ }],
+ ['safe_browsing==2', {
+ 'defines': [
+ # TODO(nparker): Remove existing uses of MOBILE_SAFE_BROWSING
+ 'MOBILE_SAFE_BROWSING',
+ 'SAFE_BROWSING_SERVICE',
+ ],
+ }],
], # conditions for 'target_defaults'
'target_conditions': [
['<(use_libpci)==1', {
@@ -3032,8 +3035,8 @@
['<(use_glib)==1 and >(nacl_untrusted_build)==0', {
'defines': ['USE_GLIB=1'],
}],
- ['<(use_nss)==1 and >(nacl_untrusted_build)==0', {
- 'defines': ['USE_NSS=1'],
+ ['<(use_nss_certs)==1 and >(nacl_untrusted_build)==0', {
+ 'defines': ['USE_NSS_CERTS=1'],
}],
['<(chromeos)==1 and >(nacl_untrusted_build)==0', {
'defines': ['OS_CHROMEOS=1'],
@@ -3603,8 +3606,6 @@
'-pthread',
'-fno-strict-aliasing', # See http://crbug.com/32204
'-Wall',
- # TODO(evan): turn this back on once all the builds work.
- # '-Wextra',
# Don't warn about unused function params. We use those everywhere.
'-Wno-unused-parameter',
# Don't warn about the "struct foo f = {0};" initialization pattern.
@@ -3676,6 +3677,12 @@
'-fomit-frame-pointer',
],
}],
+ ['OS!="android"', {
+ 'defines': [
+ '_LARGEFILE_SOURCE',
+ '_LARGEFILE64_SOURCE',
+ ],
+ }],
['OS=="linux" and target_arch=="ia32"', {
'ldflags': [
'-Wl,--no-as-needed',
@@ -4025,6 +4032,8 @@
'-no-integrated-as',
'-B<(android_toolchain)', # Else /usr/bin/as gets picked up.
],
+ }],
+ ['clang==1 and linux_use_bundled_gold==0', {
'ldflags': [
# Let clang find the ld.gold in the NDK.
'--gcc-toolchain=<(android_toolchain)/..',
@@ -4076,10 +4085,6 @@
'cflags!': [
'-fstack-protector', # stack protector is always enabled on arm64.
],
- }],
- # TODO: Remove webview test once webview fully compiles from
- # Chromium. crbug.com/440793
- ['OS=="android" and android_webview_build==0', {
'ldflags': [
'-fuse-ld=gold',
],
@@ -4092,38 +4097,74 @@
'target_conditions': [
['_toolset=="target"', {
'conditions': [
- ['android_webview_build==0', {
+ ['mips_arch_variant=="r6"', {
'conditions': [
- ['mips_arch_variant=="r6"', {
- 'cflags': ['-mips32r6', '-Wa,-mips32r6'],
- 'conditions': [
- ['OS=="android"', {
- 'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
- }],
- ],
+ ['clang==1', {
+ 'cflags': [ '-target mipsel-linux-gnu', '-march=mips32r6', ],
+ 'ldflags': [ '-target mipsel-linux-gnu', ],
+ }, { # clang==0
+ 'cflags': ['-mips32r6', '-Wa,-mips32r6', ],
}],
- ['mips_arch_variant=="r2"', {
- 'cflags': ['-mips32r2', '-Wa,-mips32r2'],
- 'conditions': [
- ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
- 'cflags': ['-m<(mips_fpu_mode)'],
- }],
- ],
+ ['clang==0 and OS=="android"', {
+ 'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
}],
- ['mips_arch_variant=="r1"', {
- 'cflags': ['-mips32', '-Wa,-mips32'],
- }],
- ['mips_dsp_rev==1', {
- 'cflags': ['-mdsp'],
- }],
- ['mips_dsp_rev==2', {
- 'cflags': ['-mdspr2'],
- }],
- ],
- 'cflags': [
- '-m<(mips_float_abi)-float'
],
}],
+ ['mips_arch_variant=="r2"', {
+ 'conditions': [
+ ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
+ 'cflags': ['-m<(mips_fpu_mode)'],
+ }],
+ ['clang==1', {
+ 'conditions': [
+ ['OS=="android"', {
+ 'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32r2'],
+ 'ldflags': [ '-target mipsel-linux-android', ],
+ }],
+ ],
+ }, { # clang==0
+ 'cflags': ['-mips32r2', '-Wa,-mips32r2', ],
+ }],
+ ],
+ }],
+ ['mips_arch_variant=="r1"', {
+ 'conditions': [
+ ['clang==1', {
+ 'conditions': [
+ ['OS=="android"', {
+ 'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32'],
+ 'ldflags': [ '-target mipsel-linux-android', ],
+ }],
+ ],
+ }, { # clang==0
+ 'cflags': ['-mips32', '-Wa,-mips32', ],
+ }],
+ ],
+ }],
+ ['clang==1', {
+ 'cflags!': [
+ # Clang does not support the following options.
+ '-finline-limit=64',
+ ],
+ 'cflags': [
+ # TODO(gordanac) Enable integrated-as.
+ '-no-integrated-as',
+ '-B<(android_toolchain)', # Else /usr/bin/as gets picked up.
+ ],
+ 'ldflags': [
+ # Let clang find the ld in the NDK.
+ '--gcc-toolchain=<(android_toolchain)/..',
+ ],
+ }],
+ ['mips_dsp_rev==1', {
+ 'cflags': ['-mdsp'],
+ }],
+ ['mips_dsp_rev==2', {
+ 'cflags': ['-mdspr2'],
+ }],
+ ],
+ 'cflags': [
+ '-m<(mips_float_abi)-float'
],
'ldflags': [
'-Wl,--no-keep-memory'
@@ -4138,17 +4179,13 @@
'target_conditions': [
['_toolset=="target"', {
'conditions': [
- ['android_webview_build==0', {
- 'conditions': [
- ['mips_arch_variant=="r6"', {
- 'cflags': ['-mips64r6', '-Wa,-mips64r6'],
- 'ldflags': ['-mips64r6'],
- }],
- ['mips_arch_variant=="r2"', {
- 'cflags': ['-mips64r2', '-Wa,-mips64r2'],
- 'ldflags': ['-mips64r2'],
- }],
- ],
+ ['mips_arch_variant=="r6"', {
+ 'cflags': ['-mips64r6', '-Wa,-mips64r6'],
+ 'ldflags': ['-mips64r6'],
+ }],
+ ['mips_arch_variant=="r2"', {
+ 'cflags': ['-mips64r2', '-Wa,-mips64r2'],
+ 'ldflags': ['-mips64r2'],
}],
],
'cflags_cc': [
@@ -4517,11 +4554,16 @@
'-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
],
}],
- ['linux_use_bundled_gold==1', {
+ ['linux_use_bundled_gold==1 and '
+ 'not (clang==0 and (use_lto==1 or use_lto_o2==1))', {
# Put our binutils, which contains gold in the search path. We pass
# the path to gold to the compiler. gyp leaves unspecified what the
# cwd is when running the compiler, so the normal gyp path-munging
# fails us. This hack gets the right path.
+ #
+ # Disabled when using GCC LTO because GCC also uses the -B search
+ # path at link time to find "as", and our bundled "as" can only
+ # target x86.
'ldflags': [
'-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
],
@@ -4668,8 +4710,13 @@
'-fstack-protector',
'-fno-short-enums',
'-finline-limit=64',
- '-Wa,--noexecstack',
'<@(release_extra_cflags)',
+ '--sysroot=<(android_ndk_sysroot)',
+ # NOTE: The stlport header include paths below are specified in
+ # cflags rather than include_dirs because they need to come
+ # after include_dirs.
+ # The include ordering here is important; change with caution.
+ '-isystem<(android_stlport_include)',
],
'defines': [
'ANDROID',
@@ -4677,15 +4724,43 @@
'USE_STLPORT=1',
'_STLP_USE_PTR_SPECIALIZATIONS=1',
'CHROME_BUILD_ID="<(chrome_build_id)"',
+ # The NDK has these things, but doesn't define the constants
+ # to say that it does. Define them here instead.
+ 'HAVE_SYS_UIO_H',
],
'ldflags!': [
'-pthread', # Not supported by Android toolchain.
],
'ldflags': [
'-Wl,--no-undefined',
+ '--sysroot=<(android_ndk_sysroot)',
+ '-nostdlib',
+ '-L<(android_stlport_libs_dir)',
+ # Don't allow visible symbols from libgcc or stlport to be
+ # re-exported.
+ '-Wl,--exclude-libs=libgcc.a',
+ '-Wl,--exclude-libs=libstlport_static.a',
+ # Don't allow visible symbols from libraries that contain
+ # assembly code with symbols that aren't hidden properly.
+ # http://crbug.com/448386
+ '-Wl,--exclude-libs=libcommon_audio.a',
+ '-Wl,--exclude-libs=libcommon_audio_neon.a',
+ '-Wl,--exclude-libs=libcommon_audio_sse2.a',
+ '-Wl,--exclude-libs=libiSACFix.a',
+ '-Wl,--exclude-libs=libisac_neon.a',
+ '-Wl,--exclude-libs=libopus.a',
+ '-Wl,--exclude-libs=libvpx.a',
+ ],
+ 'libraries': [
+ '-l<(android_stlport_library)',
+ # Manually link the libgcc.a that the cross compiler uses.
+ '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+ '-lc',
+ '-ldl',
+ '-lm',
],
'conditions': [
- ['component=="static_library" and android_webview_build==0', {
+ ['component=="static_library"', {
'target_conditions': [
['use_native_jni_exports==0', {
# Use a linker version script to strip JNI exports from
@@ -4741,112 +4816,12 @@
'-mllvm -asan-globals=0',
],
}],
- ['android_webview_build==0', {
- 'defines': [
- # The NDK has these things, but doesn't define the constants
- # to say that it does. Define them here instead.
- 'HAVE_SYS_UIO_H',
- ],
- 'cflags': [
- '--sysroot=<(android_ndk_sysroot)',
- ],
- 'ldflags': [
- '--sysroot=<(android_ndk_sysroot)',
- '-nostdlib',
- # Don't allow visible symbols from libgcc or stlport to be
- # re-exported.
- '-Wl,--exclude-libs=libgcc.a',
- '-Wl,--exclude-libs=libstlport_static.a',
- # Don't allow visible symbols from libraries that contain
- # assembly code with symbols that aren't hidden properly.
- # http://crbug.com/448386
- '-Wl,--exclude-libs=libcommon_audio.a',
- '-Wl,--exclude-libs=libcommon_audio_neon.a',
- '-Wl,--exclude-libs=libcommon_audio_sse2.a',
- '-Wl,--exclude-libs=libiSACFix.a',
- '-Wl,--exclude-libs=libisac_neon.a',
- '-Wl,--exclude-libs=libopus.a',
- '-Wl,--exclude-libs=libvpx.a',
- ],
- 'libraries': [
- '-l<(android_stlport_library)',
- # Manually link the libgcc.a that the cross compiler uses.
- '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
- '-lc',
- '-ldl',
- '-lm',
- ],
- }],
- ['android_webview_build==1', {
- 'cflags': [
- # Android predefines this as 1; undefine it here so Chromium
- # can redefine it later to be 2 for chromium code and unset
- # for third party code. This works because cflags are added
- # before defines.
- '-U_FORTIFY_SOURCE',
- # Disable any additional warnings enabled by the Android build system but which
- # chromium does not build cleanly with (when treating warning as errors).
- # Things that are part of -Wextra:
- '-Wno-extra', # Enabled by -Wextra, but no specific flag
- '-Wno-ignored-qualifiers',
- '-Wno-type-limits',
- '-Wno-unused-but-set-variable',
- ],
- 'cflags_cc': [
- # Other things unrelated to -Wextra:
- '-Wno-non-virtual-dtor',
- '-Wno-sign-promo',
- ],
- 'libraries': [
- '-ldl',
- ],
- }],
- ['android_webview_build==1', {
- 'target_conditions': [
- ['chromium_code==0', {
- 'cflags': [
- # There is a class of warning which:
- # 1) Android always enables and also treats as errors
- # 2) Chromium ignores in third party code
- # So we re-enable those warnings when building Android.
- '-Wno-address',
- '-Wno-format-security',
- '-Wno-return-type',
- '-Wno-sequence-point',
- ],
- 'cflags_cc': [
- '-Wno-non-virtual-dtor',
- ],
- }],
- ],
- }],
['target_arch == "arm" and order_profiling==0', {
'ldflags': [
# Enable identical code folding to reduce size.
'-Wl,--icf=<(gold_icf_level)',
],
}],
- # 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)',
- ],
- 'ldflags': [
- '-L<(android_stlport_libs_dir)',
- ],
- }, { # else: android_webview_build!=0
- 'aosp_build_settings': {
- # Specify that we want to statically link stlport from the
- # NDK. This will provide all the include and library paths
- # automatically at build time, and link the right library.
- 'LOCAL_NDK_STL_VARIANT': 'stlport_static',
- },
- }],
['target_arch=="ia32"', {
# The x86 toolchain currently has problems with stack-protector.
'cflags!': [
@@ -4885,19 +4860,13 @@
['_type=="shared_library" or _type=="loadable_module"', {
'ldflags': [
'-Wl,-shared,-Bsymbolic',
+ # crtbegin_so.o should be the last item in ldflags.
+ '<(android_ndk_lib)/crtbegin_so.o',
],
- 'conditions': [
- ['android_webview_build==0', {
- 'ldflags': [
- # crtbegin_so.o should be the last item in ldflags.
- '<(android_ndk_lib)/crtbegin_so.o',
- ],
- 'libraries': [
- # crtend_so.o needs to be the last item in libraries.
- # Do not add any libraries after this!
- '<(android_ndk_lib)/crtend_so.o',
- ],
- }],
+ 'libraries': [
+ # crtend_so.o needs to be the last item in libraries.
+ # Do not add any libraries after this!
+ '<(android_ndk_lib)/crtend_so.o',
],
}],
],
@@ -5167,6 +5136,16 @@
# specified or not.
'-fno-strict-aliasing', # See http://crbug.com/32204.
],
+ 'conditions': [
+ ['branding=="Chrome" and buildtype=="Official"', {
+ 'OTHER_CFLAGS': [
+ # The Google Chrome Framework dSYM generated by dsymutil has
+ # grown larger than 4GB, which dsymutil can't handle. Reduce
+ # the amount of debug symbols.
+ '-gline-tables-only', # See http://crbug.com/479841
+ ]
+ }],
+ ],
},
'target_conditions': [
['_type=="executable"', {
@@ -5546,6 +5525,11 @@
4512, # Assignment operator could not be generated
4610, # Object can never be instantiated
4996, # 'X': was declared deprecated (for GetVersionEx).
+
+ # These are variable shadowing warnings that are new in VS2015. We
+ # should work through these at some point -- they may be removed from
+ # the RTM release in the /W4 set.
+ 4456, 4457, 4458, 4459,
],
'msvs_settings': {
'VCCLCompilerTool': {
@@ -5681,6 +5665,13 @@
],
},
}],
+ ['clang==1 and clang_use_chrome_plugins==1', {
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': [
+ '<@(clang_chrome_plugins_flags)',
+ ],
+ },
+ }],
],
},
},
@@ -5770,6 +5761,19 @@
}],
],
}],
+ ['sanitizer_coverage!=0', {
+ # TODO(asan/win): Move this down into the general
+ # win-target_defaults section once the 64-bit asan runtime
+ # exists. See crbug.com/345874.
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': [
+ '-fsanitize-coverage=<(sanitizer_coverage)',
+ ],
+ 'defines': [
+ 'SANITIZER_COVERAGE',
+ ],
+ },
+ }],
],
},
},
@@ -5813,45 +5817,6 @@
],
},
}],
- # In the android webview build, force host targets to be compiled with clang
- # as the hermetic host gcc is very old on some platforms. This is already
- # the default on the current development version of AOSP but we force it
- # here in case we need to compile against an older release version. We also
- # explicitly set it to false for target binaries to avoid causing problems
- # for the work to enable clang by default in AOSP. We also force the use of
- # libstdc++ on host as peculiarities of the android gyp backend mean that
- # using libc++ doesn't work, and Chromium doesn't yet require a more modern
- # C++ library.
- ['android_webview_build==1', {
- 'target_defaults': {
- 'target_conditions': [
- ['_toolset=="host"', {
- 'aosp_build_settings': {
- 'LOCAL_CLANG': 'true',
- 'LOCAL_CXX_STL': 'libstdc++',
- },
- }, { # else: _toolset != "host"
- 'aosp_build_settings': {
- 'LOCAL_CLANG': 'false',
- },
- }],
- ],
- },
- }],
- # We need a special case to handle the android webview build on mac because
- # the host gcc there doesn't accept this flag, but the target gcc may
- # require it.
- ['gcc_version>=48 and android_webview_build==1 and host_os=="mac"', {
- 'target_defaults': {
- 'target_conditions': [
- ['_toolset=="host"', {
- 'cflags!': [
- '-Wno-unused-local-typedefs',
- ],
- }],
- ],
- },
- }],
['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
'and OS!="win"', {
'make_global_settings': [
@@ -5921,6 +5886,17 @@
'cflags': [
'-flto',
],
+ 'xcode_settings': {
+ 'LLVM_LTO': 'YES',
+ },
+ }],
+ # Work-around for http://openradar.appspot.com/20356002
+ ['_toolset=="target" and _type!="static_library"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-Wl,-all_load',
+ ],
+ },
}],
],
},
@@ -5947,6 +5923,25 @@
],
},
}],
+ # Apply a lower LTO optimization level in non-official builds.
+ ['use_lto==1 and clang==1 and buildtype!="Official"', {
+ 'target_defaults': {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'ldflags': [
+ '-Wl,--plugin-opt,O1',
+ ],
+ }],
+ ['_toolset=="target" and _type!="static_library"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-Wl,-mllvm,-O1',
+ ],
+ },
+ }],
+ ],
+ },
+ }],
['use_lto==1 and clang==1 and (target_arch=="ia32" or target_arch=="x64")', {
'target_defaults': {
'target_conditions': [
@@ -6030,6 +6025,74 @@
],
},
}],
+ ['cfi_derived_cast==1', {
+ 'target_defaults': {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '-fsanitize=cfi-derived-cast',
+ ],
+ 'ldflags': [
+ '-fsanitize=cfi-derived-cast',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-fsanitize=cfi-derived-cast',
+ ],
+ },
+ }],
+ ['_toolset=="target" and _type!="static_library"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-fsanitize=cfi-derived-cast',
+ ],
+ },
+ }],
+ ],
+ },
+ }],
+ ['cfi_unrelated_cast==1', {
+ 'target_defaults': {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '-fsanitize=cfi-unrelated-cast',
+ ],
+ 'ldflags': [
+ '-fsanitize=cfi-unrelated-cast',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-fsanitize=cfi-unrelated-cast',
+ ],
+ },
+ }],
+ ['_toolset=="target" and _type!="static_library"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-fsanitize=cfi-unrelated-cast',
+ ],
+ },
+ }],
+ ],
+ },
+ }],
+ ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
+ 'target_defaults': {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '-fsanitize-blacklist=<(cfi_blacklist)',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-fsanitize-blacklist=<(cfi_blacklist)',
+ ],
+ },
+ }],
+ ],
+ },
+ }],
],
'xcode_settings': {
# DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 15441a9..22cb45a 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -27,6 +27,9 @@
# Set to true to enable dcheck in Release builds.
dcheck_always_on = false
+
+ # Set to true to compile with the OpenGL ES 2.0 conformance tests.
+ internal_gles2_conform_tests = false
}
# TODO(brettw) Most of these should be removed. Instead of global feature
@@ -119,14 +122,12 @@
}
if (use_openssl) {
defines += [ "USE_OPENSSL=1" ]
- if (use_openssl_certs) {
- defines += [ "USE_OPENSSL_CERTS=1" ]
- }
- } else if (use_nss_certs) {
- # USE_NSS really means "use nss for certificate validation and storage"
- # (like USE_OPENSSL_CERTS) and not "we're linking to NSS." It might be nice
- # to rename this but we're hoping to transition away from NSS.
- defines += [ "USE_NSS=1" ]
+ }
+ if (use_openssl_certs) {
+ defines += [ "USE_OPENSSL_CERTS=1" ]
+ }
+ if (use_nss_certs) {
+ defines += [ "USE_NSS_CERTS=1" ]
}
if (use_ozone) {
defines += [ "USE_OZONE=1" ]
@@ -225,6 +226,18 @@
if (enable_pre_sync_backup) {
defines += [ "ENABLE_PRE_SYNC_BACKUP" ]
}
+ if (enable_video_hole) {
+ defines += [ "VIDEO_HOLE=1" ]
+ }
+ if (safe_browsing_mode == 1) {
+ defines += [ "FULL_SAFE_BROWSING" ]
+ defines += [ "SAFE_BROWSING_CSD" ]
+ defines += [ "SAFE_BROWSING_DB_LOCAL" ]
+ defines += [ "SAFE_BROWSING_SERVICE" ]
+ } else if (safe_browsing_mode == 2) {
+ defines += [ "MOBILE_SAFE_BROWSING" ]
+ defines += [ "SAFE_BROWSING_SERVICE" ]
+ }
}
# Debug/release ----------------------------------------------------------------
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 8e30c4a..455ec0d 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -17,27 +17,12 @@
# Use "is_*" names for intrinsic platform descriptions and build modes, and
# "use_*" names for optional features libraries, and configurations.
-# TODO(dpranke): The os and cpu_arch variables exist for backwards
-# compatibility and should be deleted once all of the build files and
-# bots have been updated to use current_cpu/target_cpu and
-# current_os/target_os instead.
-
if (target_os == "") {
- if (defined(os)) {
- # If os is defined, it was set in an args file and needs to be
- # used for backwards-compatibility.
- target_os = os
- } else {
- target_os = host_os
- }
+ target_os = host_os
}
if (target_cpu == "") {
- if (defined(cpu_arch)) {
- # If cpu_arch is defined, it was set in an args file and needs to be
- # used for backwards-compatibility.
- target_cpu = cpu_arch
- } else if (target_os == "android") {
+ if (target_os == "android") {
# If we're building for Android, we should assume that we want to
# build for ARM by default, not the host_cpu (which is likely x64).
# This allows us to not have to specify both target_os and target_cpu
@@ -56,13 +41,6 @@
}
declare_args() {
- # TODO(dpranke): These values are here for backwards compatibility and
- # should be deleted when all of the builders and configs have been updated.
- cpu_arch = target_cpu
- os = target_os
- build_cpu_arch = host_cpu
- build_os = host_os
-
# How many symbols to include in the build. This affects the performance of
# the build since the symbols are large and dealing with them is slow.
# 2 means regular build with symbols.
@@ -115,10 +93,6 @@
}
}
-# TODO(dpranke): Remove these asserts when os and cpu_arch are removed.
-assert(current_cpu == cpu_arch)
-assert(current_os == os)
-
# =============================================================================
# OS DEFINITIONS
# =============================================================================
@@ -539,8 +513,8 @@
} else if (is_nacl) {
# TODO(GYP): This will need to change when we get NaCl working
# on multiple platforms, but this whole block of code (how we define
- # host_toolchain) needs to be reworked regardless to key off of build_os
- # and build_cpu_arch rather than the is_* variables.
+ # host_toolchain) needs to be reworked regardless to key off of host_os
+ # and host_cpu rather than the is_* variables.
host_toolchain = "//build/toolchain/linux:clang_x64"
}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 5a27e78..77ee311 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -30,11 +30,6 @@
android_sdk_version = default_android_sdk_version
android_sdk_build_tools_version = default_android_sdk_build_tools_version
- # This is set when building the Android WebView inside the Android build
- # system, using the 'android' gyp backend. The WebView code is still built
- # when this is unset, but builds using the normal chromium build system.
- is_android_webview_build = false
-
android_default_keystore_path =
"//build/android/ant/chromium-debug.keystore"
android_default_keystore_name = "chromiumdebugkey"
@@ -44,6 +39,9 @@
# identifying various build artifacts corresponding to a particular build of
# chrome (e.g. where to find archived symbols).
android_chrome_build_id = "\"\""
+
+ # Set to true to run findbugs on JAR targets.
+ run_findbugs = false
}
# Host stuff -----------------------------------------------------------------
@@ -189,8 +187,4 @@
} else {
assert(false, "Unknown Android ABI: " + current_cpu)
}
-} else {
- if (!defined(is_android_webview_build)) {
- is_android_webview_build = false
- }
}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 8920e95..ab773ea 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -62,6 +62,44 @@
}
}
+template("findbugs") {
+ jar_path = invoker.jar_path
+
+ build_config = invoker.build_config
+
+ action(target_name) {
+ script = "//build/android/findbugs_diff.py"
+ depfile = "$target_gen_dir/$target_name.d"
+ result_path = "$target_gen_dir/$target_name/result.xml"
+ exclusions_file = "//build/android/findbugs_filter/findbugs_exclude.xml"
+
+ rebased_build_config = rebase_path(build_config, root_build_dir)
+
+ inputs = [
+ "//build/android/pylib/utils/findbugs.py",
+ exclusions_file,
+ jar_path,
+ ]
+
+ outputs = [
+ depfile,
+ result_path,
+ ]
+
+ args = [
+ "--depfile",
+ rebase_path(depfile, root_build_dir),
+ "--exclude",
+ rebase_path(exclusions_file, root_build_dir),
+ "--auxclasspath-gyp",
+ "@FileArg($rebased_build_config:javac:classpath)",
+ "--output-file",
+ rebase_path(result_path, root_build_dir),
+ rebase_path(jar_path, root_build_dir),
+ ]
+ }
+}
+
template("dex") {
set_sources_assignment_filter([])
if (defined(invoker.testonly)) {
@@ -188,7 +226,8 @@
dep_name = get_label_info(d, "name")
possible_deps_configs += [ "$dep_gen_dir/$dep_name.build_config" ]
}
- rebase_possible_deps_configs = rebase_path(possible_deps_configs)
+ rebase_possible_deps_configs =
+ rebase_path(possible_deps_configs, root_build_dir)
outputs = [
depfile,
@@ -250,6 +289,19 @@
args += [ "--bypass-platform-checks" ]
}
+ if (defined(invoker.apk_under_test)) {
+ deps += [ invoker.apk_under_test ]
+ apk_under_test_gen_dir =
+ get_label_info(invoker.apk_under_test, "target_gen_dir")
+ apk_under_test_name = get_label_info(invoker.apk_under_test, "name")
+ apk_under_test_config =
+ "$apk_under_test_gen_dir/$apk_under_test_name.build_config"
+ args += [
+ "--tested-apk-config",
+ rebase_path(apk_under_test_config, root_build_dir),
+ ]
+ }
+
if (is_android_resources || is_apk) {
assert(defined(invoker.resources_zip))
args += [
@@ -262,6 +314,8 @@
"--android-manifest",
rebase_path(invoker.android_manifest, root_build_dir),
]
+ } else {
+ assert(!is_apk, "apk build configs require an android_manifest")
}
if (defined(invoker.custom_package)) {
args += [
@@ -914,6 +968,14 @@
jar_path = _jar_path
java_files = _java_files
}
+
+ if (run_findbugs) {
+ _final_datadeps += [ ":${_template_name}__findbugs" ]
+ findbugs("${_template_name}__findbugs") {
+ build_config = _build_config
+ jar_path = _jar_path
+ }
+ }
}
_final_deps += [ ":${_template_name}__dex" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index a056997..39b2f39 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -49,9 +49,6 @@
script = "//base/android/jni_generator/jni_generator.py"
depfile = "$target_gen_dir/$target_name.{{source_name_part}}.d"
sources = invoker.sources
- inputs = [
- jni_generator_include,
- ]
outputs = [
depfile,
"${jni_output_dir}/{{source_name_part}}_jni.h",
@@ -66,7 +63,7 @@
"--output_dir",
rebase_path(jni_output_dir, root_build_dir),
"--includes",
- rebase_path(jni_generator_include, "//"),
+ rebase_path(jni_generator_include, jni_output_dir),
"--native_exports_optional",
]
if (defined(invoker.jni_generator_jarjar_file)) {
@@ -166,7 +163,6 @@
script = "//base/android/jni_generator/jni_generator.py"
sources = [
jar_file,
- jni_generator_include,
]
outputs = [
depfile,
@@ -185,7 +181,7 @@
"--output_dir",
rebase_path(jni_output_dir, root_build_dir),
"--includes",
- rebase_path(jni_generator_include, root_build_dir),
+ rebase_path(jni_generator_include, jni_output_dir),
"--native_exports_optional",
]
}
@@ -733,7 +729,7 @@
# datadeps, testonly
#
# Example
-# java_library("foo") {
+# java_binary("foo") {
# java_files = [ "org/chromium/foo/FooMain.java" ]
# deps = [ ":bar_java" ]
# main_class = "org.chromium.foo.FooMain"
@@ -776,7 +772,65 @@
}
}
-# Declare an java library target
+# Declare a Junit executable target
+#
+# This target creates an executable from java code for running as a junit test
+# suite. The executable will be in the output folder's /bin/ directory.
+#
+# Variables
+# deps: Specifies the dependencies of this target. Java targets in this list
+# will be included in the executable (and the javac classpath).
+#
+# java_files: List of .java files included in this library.
+# srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
+# will be added to java_files and be included in this library.
+# srcjars: List of srcjars to be included in this library, together with the
+# ones obtained from srcjar_deps.
+#
+# chromium_code: If true, extra analysis warning/errors will be enabled.
+#
+# Example
+# junit_binary("foo") {
+# java_files = [ "org/chromium/foo/FooTest.java" ]
+# deps = [ ":bar_java" ]
+# }
+template("junit_binary") {
+ set_sources_assignment_filter([])
+
+ java_binary(target_name) {
+ bypass_platform_checks = true
+ main_class = "org.chromium.testing.local.JunitTestMain"
+ testonly = true
+
+ if (defined(invoker.DEPRECATED_java_in_dir)) {
+ DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir
+ }
+ if (defined(invoker.chromium_code)) {
+ chromium_code = invoker.chromium_code
+ }
+ deps = [
+ "//testing/android/junit:junit_test_support",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ "//third_party/robolectric:robolectric_java",
+ "//third_party/robolectric:android-all-4.3_r2-robolectric-0",
+ ]
+ if (defined(invoker.deps)) {
+ deps += invoker.deps
+ }
+ if (defined(invoker.java_files)) {
+ java_files = invoker.java_files
+ }
+ if (defined(invoker.srcjar_deps)) {
+ srcjar_deps = invoker.srcjar_deps
+ }
+ if (defined(invoker.srcjars)) {
+ srcjars = invoker.srcjars
+ }
+ }
+}
+
+# Declare a java library target
#
# Variables
# deps: Specifies the dependencies of this target. Java targets in this list
@@ -874,7 +928,7 @@
}
}
-# Declare an java library target for a prebuilt jar
+# Declare a java library target for a prebuilt jar
#
# Variables
# deps: Specifies the dependencies of this target. Java targets in this list
@@ -1107,6 +1161,8 @@
# native_libs: List paths of native libraries to include in this apk. If these
# libraries depend on other shared_library targets, those dependencies will
# also be included in the apk.
+# apk_under_test: For an instrumentation test apk, this is the target of the
+# tested apk.
# testonly: Marks this target as "test-only".
#
# DEPRECATED_java_in_dir: Directory containing java files. All .java files in
@@ -1138,9 +1194,10 @@
}
assert(defined(invoker.final_apk_path) || defined(invoker.apk_name))
+ assert(defined(invoker.android_manifest))
gen_dir = "$target_gen_dir/$target_name"
base_path = "$gen_dir/$target_name"
- _build_config = "$base_path.build_config"
+ _build_config = "$target_gen_dir/$target_name.build_config"
resources_zip_path = "$base_path.resources.zip"
all_resources_zip_path = "$base_path.resources.all.zip"
jar_path = "$base_path.jar"
@@ -1223,6 +1280,7 @@
}
}
+ _android_manifest = invoker.android_manifest
_rebased_build_config = rebase_path(_build_config, root_build_dir)
write_build_config("${_template_name}__build_config") {
@@ -1230,11 +1288,16 @@
dex_path = final_dex_path
resources_zip = resources_zip_path
build_config = _build_config
+ android_manifest = _android_manifest
if (defined(invoker.deps)) {
deps = invoker.deps
}
+ if (defined(invoker.apk_under_test)) {
+ apk_under_test = invoker.apk_under_test
+ }
+
native_libs = _native_libs
}
@@ -1243,7 +1306,7 @@
final_deps += [ ":${_template_name}__process_resources" ]
process_resources("${_template_name}__process_resources") {
srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
- android_manifest = invoker.android_manifest
+ android_manifest = _android_manifest
resource_dirs = [ "//build/android/ant/empty/res" ]
zip_path = resources_zip_path
generate_constant_ids = true
@@ -1289,7 +1352,7 @@
supports_android = true
requires_android = true
override_build_config = _build_config
- android_manifest = invoker.android_manifest
+ android_manifest = _android_manifest
chromium_code = true
if (defined(invoker.java_files)) {
java_files = invoker.java_files
@@ -1397,7 +1460,7 @@
final_deps += [ ":${_template_name}__create" ]
create_apk("${_template_name}__create") {
apk_path = _final_apk_path
- android_manifest = invoker.android_manifest
+ android_manifest = _android_manifest
resources_zip = all_resources_zip_path
dex_path = final_dex_path
load_library_from_apk = _load_library_from_apk
@@ -1490,13 +1553,12 @@
}
android_apk(target_name) {
- _apk_name = apk_name
- final_apk_path = "$root_build_dir/${_apk_name}_apk/${_apk_name}-debug.apk"
+ final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk"
java_files = [
- "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
- "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
+ "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
+ "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
]
- android_manifest = "//testing/android/java/AndroidManifest.xml"
+ android_manifest = "//testing/android/native_test/java/AndroidManifest.xml"
native_libs = [ unittests_binary ]
if (defined(invoker.asset_location)) {
asset_location = invoker.asset_location
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 39fe251..3d96500 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -6,20 +6,29 @@
config("find_bad_constructs") {
if (clang_use_chrome_plugins) {
- cflags = [
- "-Xclang",
- "-load",
- "-Xclang",
- ]
+ cflags = []
+
+ # On Windows, the plugin is built directly into clang, so there's
+ # no need to load it dynamically.
if (is_mac || is_ios) {
- cflags += [ rebase_path(
- "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
- root_build_dir) ]
+ cflags += [
+ "-Xclang",
+ "-load",
+ "-Xclang",
+ rebase_path(
+ "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
+ root_build_dir),
+ ]
} else if (is_linux) {
- cflags += [ rebase_path(
- "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
- root_build_dir) ]
+ cflags += [
+ "-Xclang",
+ "-load",
+ "-Xclang",
+ rebase_path(
+ "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+ root_build_dir),
+ ]
}
cflags += [
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 42dc584..c217154 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -165,7 +165,7 @@
defines += [ "CR_CLANG_REVISION=" +
exec_script("//tools/clang/scripts/posix-print-revision.py",
[],
- "value") ]
+ "trim string") ]
}
# Mac-specific compiler flags setup.
@@ -194,16 +194,11 @@
cflags_objcc = [ "-fobjc-call-cxx-cdtors" ]
cflags_c += [ "-std=c99" ]
- cflags_cc += [ "-std=gnu++11" ]
ldflags += common_mac_flags
} else if (is_posix) {
# Non-Mac Posix compiler flags setup.
# -----------------------------------
- if (gcc_version >= 48) {
- cflags_cc += [ "-std=gnu++11" ]
- }
-
if (enable_profiling && !is_debug) {
# The GYP build spams this define into every compilation unit, as we do
# here, but it only appears to be used in base and a couple other places.
@@ -246,98 +241,93 @@
]
}
} else if (current_cpu == "arm") {
- # Don't set the compiler flags for the WebView build. These will come
- # from the Android build system.
- if (!is_android_webview_build) {
+ cflags += [
+ "-march=$arm_arch",
+ "-mfloat-abi=$arm_float_abi",
+ ]
+ if (arm_tune != "") {
+ cflags += [ "-mtune=$arm_tune" ]
+ }
+ if (arm_use_thumb) {
+ cflags += [ "-mthumb" ]
+ if (is_android && !is_clang) { # Clang doesn't support this option.
+ cflags += [ "-mthumb-interwork" ]
+ }
+ }
+ if (!is_clang) {
+ # Clang doesn't support these flags.
cflags += [
- "-march=$arm_arch",
- "-mfloat-abi=$arm_float_abi",
- ]
- if (arm_tune != "") {
- cflags += [ "-mtune=$arm_tune" ]
- }
- if (arm_use_thumb) {
- cflags += [ "-mthumb" ]
- if (is_android && !is_clang) { # Clang doesn't support this option.
- cflags += [ "-mthumb-interwork" ]
- }
- }
- if (!is_clang) {
- # Clang doesn't support these flags.
- cflags += [
- # The tree-sra optimization (scalar replacement for
- # aggregates enabling subsequent optimizations) leads to
- # invalid code generation when using the Android NDK's
- # compiler (r5-r7). This can be verified using
- # webkit_unit_tests' WTF.Checked_int8_t test.
- "-fno-tree-sra",
+ # The tree-sra optimization (scalar replacement for
+ # aggregates enabling subsequent optimizations) leads to
+ # invalid code generation when using the Android NDK's
+ # compiler (r5-r7). This can be verified using
+ # webkit_unit_tests' WTF.Checked_int8_t test.
+ "-fno-tree-sra",
- # The following option is disabled to improve binary
- # size and performance in gcc 4.9.
- "-fno-caller-saves",
- ]
- }
+ # The following option is disabled to improve binary
+ # size and performance in gcc 4.9.
+ "-fno-caller-saves",
+ ]
}
} else if (current_cpu == "mipsel") {
- # Don't set the compiler flags for the WebView build. These will come
- # from the Android build system.
- if (!is_android_webview_build) {
- if (mips_arch_variant == "r6") {
- cflags += [
+ if (mips_arch_variant == "r6") {
+ cflags += [
+ "-mips32r6",
+ "-Wa,-mips32r6",
+ ]
+ if (is_android) {
+ ldflags += [
"-mips32r6",
- "-Wa,-mips32r6",
- ]
- if (is_android) {
- ldflags += [
- "-mips32r6",
- "-Wl,-melf32ltsmip",
- ]
- }
- } else if (mips_arch_variant == "r2") {
- cflags += [
- "-mips32r2",
- "-Wa,-mips32r2",
- ]
- if (mips_float_abi == "hard" && mips_fpu_mode != "") {
- cflags += [ "-m$mips_fpu_mode" ]
- }
- } else if (mips_arch_variant == "r1") {
- cflags += [
- "-mips32",
- "-Wa,-mips32",
+ "-Wl,-melf32ltsmip",
]
}
-
- if (mips_dsp_rev == 1) {
- cflags += [ "-mdsp" ]
- } else if (mips_dsp_rev == 2) {
- cflags += [ "-mdspr2" ]
+ } else if (mips_arch_variant == "r2") {
+ cflags += [
+ "-mips32r2",
+ "-Wa,-mips32r2",
+ ]
+ if (mips_float_abi == "hard" && mips_fpu_mode != "") {
+ cflags += [ "-m$mips_fpu_mode" ]
}
-
- cflags += [ "-m${mips_float_abi}-float" ]
+ } else if (mips_arch_variant == "r1") {
+ cflags += [
+ "-mips32",
+ "-Wa,-mips32",
+ ]
}
+
+ if (mips_dsp_rev == 1) {
+ cflags += [ "-mdsp" ]
+ } else if (mips_dsp_rev == 2) {
+ cflags += [ "-mdspr2" ]
+ }
+
+ cflags += [ "-m${mips_float_abi}-float" ]
} else if (current_cpu == "mips64el") {
- # Don't set the compiler flags for the WebView build. These will come
- # from the Android build system.
- if (!is_android_webview_build) {
- if (mips_arch_variant == "r6") {
- cflags += [
- "-mips64r6",
- "-Wa,-mips64r6",
- ]
- ldflags += [ "-mips64r6" ]
- } else if (mips_arch_variant == "r2") {
- cflags += [
- "-mips64r2",
- "-Wa,-mips64r2",
- ]
- ldflags += [ "-mips64r2" ]
- }
+ if (mips_arch_variant == "r6") {
+ cflags += [
+ "-mips64r6",
+ "-Wa,-mips64r6",
+ ]
+ ldflags += [ "-mips64r6" ]
+ } else if (mips_arch_variant == "r2") {
+ cflags += [
+ "-mips64r2",
+ "-Wa,-mips64r2",
+ ]
+ ldflags += [ "-mips64r2" ]
}
}
defines += [ "_FILE_OFFSET_BITS=64" ]
+ if (!is_android) {
+ defines += [
+ "_LARGEFILE_SOURCE",
+ "_LARGEFILE64_SOURCE",
+ ]
+ }
+
# Omit unwind support in official builds to save space. We can use breakpad
# for these builds.
if (is_chrome_branded && is_official_build) {
@@ -418,7 +408,18 @@
# ------------------------------------
if (is_clang) {
cflags += [ "-fcolor-diagnostics" ]
+ }
+
+ # C++11 compiler flags setup.
+ # ---------------------------
+ if (is_linux || is_android || is_nacl) {
+ # gnu++11 instead of c++11 is needed because some code uses typeof() (a
+ # GNU extension).
+ # TODO(thakis): Eventually switch this to c++11 instead,
+ # http://crbug.com/427584
cflags_cc += [ "-std=gnu++11" ]
+ } else if (!is_win) {
+ cflags_cc += [ "-std=c++11" ]
}
# Android-specific flags setup.
@@ -433,15 +434,6 @@
# Clang doesn't support these flags.
cflags += [ "-finline-limit=64" ]
}
- if (is_android_webview_build) {
- # Android predefines this as 1; undefine it here so Chromium can redefine
- # it later to be 2 for chromium code and unset for third party code. This
- # works because cflags are added before defines.
- # TODO(brettw) the above comment seems incorrect. We specify defines
- # before cflags on our compiler command lines.
- cflags += [ "-U_FORTIFY_SOURCE" ]
- }
-
if (is_asan) {
# Android build relies on -Wl,--gc-sections removing unreachable code.
# ASan instrumentation for globals inhibits this and results in a library
@@ -451,11 +443,10 @@
}
defines += [ "ANDROID" ]
- if (!is_android_webview_build) {
- # The NDK has these things, but doesn't define the constants
- # to say that it does. Define them here instead.
- defines += [ "HAVE_SYS_UIO_H" ]
- }
+
+ # The NDK has these things, but doesn't define the constants
+ # to say that it does. Define them here instead.
+ defines += [ "HAVE_SYS_UIO_H" ]
# Use gold for Android for most CPU architectures.
if (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm") {
@@ -500,7 +491,7 @@
}
config("compiler_arm_fpu") {
- if (current_cpu == "arm" && !is_android_webview_build) {
+ if (current_cpu == "arm") {
cflags = [ "-mfpu=$arm_fpu" ]
}
}
@@ -573,7 +564,7 @@
# TODO(jdduke) Re-enable on mips after resolving linking
# issues with libc++ (crbug.com/456380).
- if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+ if (current_cpu != "mipsel" && current_cpu != "mips64el") {
ldflags += [ "-Wl,--warn-shared-textrel" ]
}
ldflags += [ "-nostdlib" ]
@@ -684,20 +675,6 @@
"-Wno-deprecated",
]
}
-
- if (is_android_webview_build) {
- # There is a class of warning which:
- # 1) Android always enables and also treats as errors
- # 2) Chromium ignores in third party code
- # So we re-enable those warnings when building Android.
- cflags += [
- "-Wno-address",
- "-Wno-format-security",
- "-Wno-return-type",
- "-Wno-sequence-point",
- ]
- cflags_cc += [ "-Wno-non-virtual-dtor" ]
- }
}
# rtti ------------------------------------------------------------------------
@@ -983,7 +960,7 @@
# TODO(jdduke) Re-enable on mips after resolving linking
# issues with libc++ (crbug.com/456380).
- if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+ if (current_cpu != "mipsel" && current_cpu != "mips64el") {
common_optimize_on_ldflags += [
# Warn in case of text relocations.
"-Wl,--warn-shared-textrel",
diff --git a/build/config/crypto.gni b/build/config/crypto.gni
index ee23569..7f090b7 100644
--- a/build/config/crypto.gni
+++ b/build/config/crypto.gni
@@ -14,10 +14,13 @@
use_openssl = is_android || is_mac || is_nacl || is_win
}
-# True when we're using OpenSSL for certificate verification and storage. We
-# only do this when we're using OpenSSL on desktop Linux systems. For other
-# systems (Mac/Win/Android) we use the system certificate features.
-use_openssl_certs = use_openssl && (is_linux || is_android)
+# True when we're using OpenSSL for representing certificates. When targeting
+# Android, the platform certificate library is used for certificate
+# verification. On other targets, this flag also enables OpenSSL for certificate
+# verification, but this configuration is unsupported.
+use_openssl_certs = is_android
-# Same meaning as use_openssl_certs but for NSS.
-use_nss_certs = !use_openssl && is_linux
+# True if NSS is used for certificate verification. Note that this is
+# independent from use_openssl. It is possible to use OpenSSL for the crypto
+# library, but NSS for the platform certificate library.
+use_nss_certs = is_linux
diff --git a/build/config/features.gni b/build/config/features.gni
index 783e32d..dd7b081 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -47,6 +47,9 @@
# TODO(GYP) make mac and android work.
enable_webrtc = !is_ios && !is_mac && !is_android
+ # Enables the Media Router.
+ enable_media_router = !is_ios && !is_android
+
# Enables proprietary codecs and demuxers; e.g. H264, MOV, AAC, and MP3.
proprietary_codecs = false
@@ -67,13 +70,20 @@
enable_supervised_users = !is_ios
- enable_autofill_dialog = !is_ios && !(is_android && is_android_webview_build)
+ enable_autofill_dialog = !is_ios
enable_google_now = !is_ios && !is_android
enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
enable_remoting = !is_ios && !is_android
+
+ # Enable hole punching for the protected video.
+ enable_video_hole = is_android
+
+ # Enables browser side Content Decryption Modules. Required for embedders
+ # (e.g. Android and ChromeCast) that use a browser side CDM.
+ enable_browser_cdms = is_android
}
# Additional dependent variables -----------------------------------------------
@@ -96,8 +106,6 @@
enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win)
-enable_browser_cdms = is_android
-
# Enable basic printing support and UI.
enable_basic_printing = !is_chromeos
diff --git a/build/config/gcc/gcc_version.gni b/build/config/gcc/gcc_version.gni
index f5c1c1a..6741e45 100644
--- a/build/config/gcc/gcc_version.gni
+++ b/build/config/gcc/gcc_version.gni
@@ -3,12 +3,7 @@
# found in the LICENSE file.
if (is_android) {
- import("//build/config/android/config.gni")
- if (is_android_webview_build) {
- gcc_version = 48
- } else {
- gcc_version = 49
- }
+ gcc_version = 49
} else if (current_toolchain == "//build/toolchain/cros:target" ||
current_toolchain == "//build/toolchain/linux:mipsel") {
gcc_version = exec_script("../../compiler_version.py",
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn
index 4968e2d..9c9c696 100644
--- a/build/config/linux/gtk/BUILD.gn
+++ b/build/config/linux/gtk/BUILD.gn
@@ -26,9 +26,12 @@
group("gtk") {
visibility = [
"//chrome/browser/ui/libgtk2ui",
+ "//gpu/gles2_conform_support:gles2_conform_test_windowless",
"//remoting/host",
+ "//remoting/host/it2me:remote_assistance_host",
+ "//remoting/host:remoting_me2me_host_static",
]
- direct_dependent_configs = [ ":gtk_internal_config" ]
+ public_configs = [ ":gtk_internal_config" ]
}
# Depend on "gtkprint" to get this.
@@ -38,5 +41,5 @@
group("gtkprint") {
visibility = [ "//chrome/browser/ui/libgtk2ui" ]
- direct_dependent_configs = [ ":gtkprint_internal_config" ]
+ public_configs = [ ":gtkprint_internal_config" ]
}
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 941c77a..057971d 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -15,22 +15,18 @@
sysroot = target_sysroot
} else if (is_android) {
import("//build/config/android/config.gni")
- if (!is_android_webview_build) {
- if (current_cpu == "x86") {
- sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
- } else if (current_cpu == "arm") {
- sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
- } else if (current_cpu == "mipsel") {
- sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
- } else if (current_cpu == "x64") {
- sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
- } else if (current_cpu == "arm64") {
- sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
- } else if (current_cpu == "mips64") {
- sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
- } else {
- sysroot = ""
- }
+ if (current_cpu == "x86") {
+ sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
+ } else if (current_cpu == "arm") {
+ sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
+ } else if (current_cpu == "mipsel") {
+ sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
+ } else if (current_cpu == "x64") {
+ sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
+ } else if (current_cpu == "arm64") {
+ sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
+ } else if (current_cpu == "mips64") {
+ sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
} else {
sysroot = ""
}
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 4ca22f7..8b0910f 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -97,25 +97,36 @@
# Subsystem --------------------------------------------------------------------
+# This is appended to the subsystem to specify a minimum version.
+if (current_cpu == "x64") {
+ # The number after the comma is the minimum required OS version.
+ # 5.02 = Windows Server 2003.
+ subsystem_version_suffix = ",5.02"
+} else {
+ # Don't specify a min version on x86.
+ subsystem_version_suffix = ""
+}
+
config("console") {
- ldflags = [ "/SUBSYSTEM:CONSOLE" ]
+ ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
}
config("windowed") {
- ldflags = [ "/SUBSYSTEM:WINDOWS" ]
+ ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
}
# Incremental linking ----------------------------------------------------------
incremental_linking_on_switch = [ "/INCREMENTAL" ]
incremental_linking_off_switch = [ "/INCREMENTAL:NO" ]
+if (is_debug) {
+ default_incremental_linking_switch = incremental_linking_on_switch
+} else {
+ default_incremental_linking_switch = incremental_linking_off_switch
+}
# Applies incremental linking or not depending on the current configuration.
config("default_incremental_linking") {
- if (is_debug) {
- ldflags = incremental_linking_on_switch
- } else {
- ldflags = incremental_linking_off_switch
- }
+ ldflags = default_incremental_linking_switch
}
# Explicitly on or off incremental linking
@@ -130,17 +141,13 @@
# config should be applied to large modules to turn off incremental linking
# when it won't work.
config("default_large_module_incremental_linking") {
- if (!is_debug) {
- # Default is always off in release build.
- ldflags = incremental_linking_off_switch
- } else if ((symbol_level == 0 || symbol_level == 1) &&
- (current_cpu == "x86" || !is_component_build)) {
- # When full symbols are on, don't do incremental linking for large modules
- # on 32-bit or in non-component mode as the toolchain fails due to the size
- # of the .ilk files.
+ if (symbol_level > 0 && (current_cpu == "x86" || !is_component_build)) {
+ # When symbols are on, things get so large that the tools fail due to the
+ # size of the .ilk files.
ldflags = incremental_linking_off_switch
} else {
- ldflags = incremental_linking_on_switch
+ # Otherwise just do the default incremental linking for this build type.
+ ldflags = default_incremental_linking_switch
}
}
diff --git a/build/escape_unicode.py b/build/escape_unicode.py
deleted file mode 100755
index 859ba5d..0000000
--- a/build/escape_unicode.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Convert any unicode characters found in the input file to C literals."""
-
-import codecs
-import optparse
-import os
-import sys
-
-
-def main(argv):
- parser = optparse.OptionParser()
- usage = 'Usage: %prog -o <output_dir> <input_file>'
- parser.set_usage(usage)
- parser.add_option('-o', dest='output_dir')
-
- options, arglist = parser.parse_args(argv)
-
- if not options.output_dir:
- print "output_dir required"
- return 1
-
- if len(arglist) != 2:
- print "input_file required"
- return 1
-
- in_filename = arglist[1]
-
- if not in_filename.endswith('.utf8'):
- print "input_file should end in .utf8"
- return 1
-
- out_filename = os.path.join(options.output_dir, os.path.basename(
- os.path.splitext(in_filename)[0]))
-
- WriteEscapedFile(in_filename, out_filename)
- return 0
-
-
-def WriteEscapedFile(in_filename, out_filename):
- input_data = codecs.open(in_filename, 'r', 'utf8').read()
- with codecs.open(out_filename, 'w', 'ascii') as out_file:
- for i, char in enumerate(input_data):
- if ord(char) > 127:
- out_file.write(repr(char.encode('utf8'))[1:-1])
- if input_data[i + 1:i + 2] in '0123456789abcdefABCDEF':
- out_file.write('""')
- else:
- out_file.write(char.encode('ascii'))
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 8413002..58e7ff5 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -39,12 +39,6 @@
'../base/base.gyp:base_unittests',
'../base/base.gyp:build_utf8_validator_tables#host',
'../base/base.gyp:check_example',
- '../base/base.gyp:protect_file_posix',
- '../breakpad/breakpad.gyp:core-2-minidump',
- '../breakpad/breakpad.gyp:microdump_stackwalk',
- '../breakpad/breakpad.gyp:minidump_dump',
- '../breakpad/breakpad.gyp:minidump_stackwalk',
- '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
'../cc/cc_tests.gyp:cc_perftests',
'../cc/cc_tests.gyp:cc_unittests',
'../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
@@ -56,16 +50,18 @@
'../chrome/chrome.gyp:chromedriver_unittests',
'../chrome/chrome.gyp:interactive_ui_tests',
'../chrome/chrome.gyp:load_library_perf_tests',
- '../chrome/chrome.gyp:service_discovery_sniffer',
+ '../chrome/chrome.gyp:performance_browser_tests',
'../chrome/chrome.gyp:sync_integration_tests',
'../chrome/chrome.gyp:sync_performance_tests',
'../chrome/chrome.gyp:unit_tests',
'../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
+ '../cloud_print/cloud_print.gyp:cloud_print_unittests',
'../components/components.gyp:network_hints_browser',
+ '../components/components.gyp:policy_templates',
'../components/components.gyp:webui_generator',
+ '../components/components_tests.gyp:components_browsertests',
'../components/components_tests.gyp:components_perftests',
'../components/components_tests.gyp:components_unittests',
- '../components/nacl.gyp:nacl_loader_unittests',
'../content/content.gyp:content_app_browser',
'../content/content.gyp:content_app_child',
'../content/content_shell_and_tests.gyp:content_browsertests',
@@ -92,6 +88,9 @@
'../gpu/gpu.gyp:gl_tests',
'../gpu/gpu.gyp:gpu_perftests',
'../gpu/gpu.gyp:gpu_unittests',
+ '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support', # TODO(GYP) crbug.com/471920
+ '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test', # TODO(GYP) crbug.com/471920
+ '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test', # TODO(GYP) crbug.com/471903 to make this complete.
'../ipc/ipc.gyp:ipc_perftests',
'../ipc/ipc.gyp:ipc_tests',
'../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
@@ -121,9 +120,43 @@
'../net/net.gyp:run_testserver',
'../net/net.gyp:stress_cache',
'../net/net.gyp:tld_cleanup',
- '../ppapi/ppapi_internal.gyp:*', # TODO(GYP) - list all of the examples explicitly.
- '../ppapi/ppapi_internal.gyp:ppapi_tests', # TODO(GYP): Split out the examples and tests
+ '../ppapi/ppapi_internal.gyp:ppapi_example_audio',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_audio_input',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_c_stub',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_cc_stub',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_compositor',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_crxfs',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_enumerate_devices',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_file_chooser',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_flash_topmost',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_gamepad',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_gles2',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_gles2_spinning_cube',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_graphics_2d',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_ime',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_input',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_audio',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_video',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_cursor',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_lock',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_paint_manager',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_post_message',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_printing',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_scaling',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_scroll',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_simple_font',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_threading',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader_file',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_vc',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode_dev',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_video_effects',
+ '../ppapi/ppapi_internal.gyp:ppapi_example_video_encode',
+ '../ppapi/ppapi_internal.gyp:ppapi_tests',
+ '../ppapi/ppapi_internal.gyp:ppapi_perftests',
'../ppapi/ppapi_internal.gyp:ppapi_unittests',
+ '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
'../printing/printing.gyp:printing_unittests',
'../skia/skia_tests.gyp:skia_unittests',
'../skia/skia.gyp:filter_fuzz_stub',
@@ -148,9 +181,9 @@
'../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
'../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
'../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
+ '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
'../third_party/pdfium/samples/samples.gyp:pdfium_test',
'../third_party/smhasher/smhasher.gyp:pmurhash',
- '../third_party/sqlite/sqlite.gyp:sqlite_shell',
'../tools/gn/gn.gyp:gn',
'../tools/gn/gn.gyp:generate_test_gn_data',
'../tools/gn/gn.gyp:gn_unittests',
@@ -164,7 +197,6 @@
'../ui/display/display.gyp:display_unittests',
'../ui/events/events.gyp:events_unittests',
'../ui/gfx/gfx_tests.gyp:gfx_unittests',
- '../ui/keyboard/keyboard.gyp:keyboard_unittests',
'../ui/message_center/message_center.gyp:message_center_unittests',
'../ui/snapshot/snapshot.gyp:snapshot_unittests',
'../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
@@ -174,28 +206,36 @@
'../v8/tools/gyp/v8.gyp:postmortem-metadata',
],
'conditions': [
+ ['clang==1', {
+ 'dependencies': [
+ '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
+ ],
+ }],
+ ['disable_nacl==0 and disable_nacl_untrusted==0', {
+ 'dependencies': [
+ '../components/nacl.gyp:nacl_loader_unittests',
+ ]
+ }],
['enable_extensions==1 and OS!="mac"', {
'dependencies': [
'../extensions/shell/app_shell.gyp:app_shell',
'../extensions/shell/app_shell.gyp:app_shell_unittests',
],
}],
- ['OS!="win"', {
+ ['enable_mdns==1', {
'dependencies': [
- '../breakpad/breakpad.gyp:symupload',
+ '../chrome/chrome.gyp:service_discovery_sniffer',
+ ]
+ }],
+ ['remoting==1', {
+ 'dependencies': [
+ '../remoting/remoting_all.gyp:remoting_all',
],
}],
- ['use_x11==1', {
+ ['remoting==1 and chromeos==0', {
'dependencies': [
- '../media/media.gyp:player_x11',
- '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
- ],
- 'conditions': [
- ['target_arch!="arm"', {
- 'dependencies': [
- '../gpu/tools/tools.gyp:compositor_model_bench',
- ],
- }],
+ '../remoting/remoting.gyp:remoting_me2me_host',
+ '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
],
}],
['toolkit_views==1', {
@@ -211,11 +251,17 @@
'../ash/ash.gyp:ash_unittests',
],
}],
+ ['use_ash==1 or chromeos== 1', {
+ 'dependencies': [
+ '../components/components.gyp:session_manager_component',
+ ]
+ }],
['use_aura==1', {
'dependencies': [
'../ui/aura/aura.gyp:aura_bench',
'../ui/aura/aura.gyp:aura_demo',
'../ui/aura/aura.gyp:aura_unittests',
+ '../ui/keyboard/keyboard.gyp:keyboard_unittests',
'../ui/wm/wm.gyp:wm_unittests',
],
}],
@@ -224,9 +270,18 @@
'../ui/ozone/ozone.gyp:ozone',
],
}],
- ['OS=="win" or OS=="mac" or chromeos==1', {
+
+
+ ['use_x11==1', {
'dependencies': [
- '../rlz/rlz.gyp:rlz_lib',
+ '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+ ],
+ 'conditions': [
+ ['target_arch!="arm"', {
+ 'dependencies': [
+ '../gpu/tools/tools.gyp:compositor_model_bench',
+ ],
+ }],
],
}],
['OS=="android"', {
@@ -275,6 +330,7 @@
'../chrome/chrome.gyp:chromedriver',
'../chrome/chrome.gyp:chromedriver_unitests',
'../chrome/chrome.gyp:interactive_ui_tests',
+ '../chrome/chrome.gyp:performance_browser_tests',
'../chrome/chrome.gyp:sync_integration_tests',
'../chrome/chrome.gyp:unit_tests',
'../extensions/extensions_tests.gyp:extensions_browsertests',
@@ -294,10 +350,38 @@
'../url/url.gyp:url_unittests',
],
}],
+ ['OS=="android" or OS=="linux"', {
+ 'dependencies': [
+ '../net/net.gyp:disk_cache_memory_test',
+ ],
+ }],
+ ['chromeos==1', {
+ 'dependencies': [
+ '../chromeos/chromeos.gyp:chromeos_unittests',
+ '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+ ]
+ }],
+ ['chromeos==1 or OS=="win" or OS=="mac"', {
+ 'dependencies': [
+ '../rlz/rlz.gyp:rlz_id',
+ '../rlz/rlz.gyp:rlz_lib',
+ '../rlz/rlz.gyp:rlz_unittests',
+ ],
+ }],
+ ['OS=="android" or OS=="linux" or os_bsd==1', {
+ 'dependencies': [
+ '../breakpad/breakpad.gyp:core-2-minidump',
+ '../breakpad/breakpad.gyp:microdump_stackwalk',
+ '../breakpad/breakpad.gyp:minidump_dump',
+ '../breakpad/breakpad.gyp:minidump_stackwalk',
+ '../breakpad/breakpad.gyp:symupload',
+ '../third_party/codesighs/codesighs.gyp:nm2tsv',
+ ],
+ }],
['OS=="linux"', {
'dependencies': [
'../breakpad/breakpad.gyp:breakpad_unittests',
- '../breakpad/breakpad.gyp:dump_syms',
+ '../breakpad/breakpad.gyp:dump_syms#host',
'../breakpad/breakpad.gyp:generate_test_dump',
'../breakpad/breakpad.gyp:minidump-2-core',
'../dbus/dbus.gyp:dbus_test_server',
@@ -306,6 +390,8 @@
'../net/net.gyp:disk_cache_memory_test',
'../net/net.gyp:flip_in_mem_edsm_server',
'../net/net.gyp:flip_in_mem_edsm_server_unittests',
+ '../net/net.gyp:epoll_quic_client',
+ '../net/net.gyp:epoll_quic_server',
'../net/net.gyp:hpack_example_generator',
'../net/net.gyp:hpack_fuzz_mutator',
'../net/net.gyp:hpack_fuzz_wrapper',
@@ -315,6 +401,7 @@
'../sandbox/sandbox.gyp:chrome_sandbox',
'../sandbox/sandbox.gyp:sandbox_linux_unittests',
'../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
+ '../third_party/sqlite/sqlite.gyp:sqlite_shell',
],
}],
['OS=="mac"', {
@@ -372,22 +459,38 @@
}],
['OS=="win"', {
'dependencies': [
- "//ui/metro_viewer",
+ '../base/base.gyp:pe_image_test',
+ '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests',
+ '../chrome_elf/chrome_elf.gyp:dll_hash_main',
+ '../components/components.gyp:wifi_test',
+ '../net/net.gyp:quic_client',
+ '../net/net.gyp:quic_server',
+ '../sandbox/sandbox.gyp:pocdll',
+ '../sandbox/sandbox.gyp:sandbox_poc',
+ '../sandbox/sandbox.gyp:sbox_integration_tests',
+ '../sandbox/sandbox.gyp:sbox_unittests',
+ '../sandbox/sandbox.gyp:sbox_validation_tests',
+ '../testing/gtest.gyp:gtest_main',
'../third_party/codesighs/codesighs.gyp:msdump2symdb',
- ],
- 'dependencies!': [
- "//crypto:crypto_unittests", # TODO(GYP)
- "//net:net_unittests", # TODO(GYP)
- ],
- }, {
- 'dependencies': [
- '../third_party/codesighs/codesighs.gyp:nm2tsv',
+ '../third_party/codesighs/codesighs.gyp:msmap2tsv',
+ '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
+ '../win8/win8.gyp:metro_viewer',
],
}],
- ['OS=="android" or OS=="linux"', {
- 'dependencies': [
- '../net/net.gyp:disk_cache_memory_test',
- ],
+ ],
+ },
+ {
+ 'target_name': 'gyp_only',
+ 'type': 'none',
+ 'conditions': [
+ ['OS=="linux" or OS=="win"', {
+ 'conditions': [
+ ['disable_nacl==0 and disable_nacl_untrusted==0', {
+ 'dependencies': [
+ '../mojo/mojo_nacl.gyp:monacl_shell', # This should not be built in chromium.
+ ]
+ }],
+ ]
}],
],
},
@@ -395,135 +498,172 @@
'target_name': 'gyp_remaining',
'type': 'none',
'conditions': [
- ['OS=="linux"', {
+ ['remoting==1', {
'dependencies': [
- '../chrome/chrome.gyp:performance_browser_tests',
- '../cloud_print/cloud_print.gyp:cloud_print_unittests',
- '../components/components.gyp:policy_templates',
- '../components/components_tests.gyp:components_browsertests',
- '../components/components_tests.gyp:components_perftests',
- '../content/content.gyp:content_app_browser',
- '../content/content.gyp:content_app_child',
- '../content/content_shell_and_tests.gyp:content_gl_benchmark',
- '../content/content_shell_and_tests.gyp:content_gl_tests',
- '../courgette/courgette.gyp:courgette',
- '../courgette/courgette.gyp:courgette_fuzz',
- '../dbus/dbus.gyp:dbus_test_server',
- '../device/device_tests.gyp:device_unittests',
- '../gin/gin.gyp:gin_v8_snapshot_fingerprint',
- '../gin/gin.gyp:gin_shell',
- '../gpu/gpu.gyp:gl_tests',
- '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
- '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
- '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
- '../media/cast/cast.gyp:cast_benchmarks',
- '../media/cast/cast.gyp:generate_barcode_video',
- '../media/cast/cast.gyp:generate_timecode_audio',
- '../media/cast/cast.gyp:tap_proxy',
- '../mojo/mojo_base.gyp:mojo_application_chromium',
- '../ppapi/ppapi_internal.gyp:ppapi_unittests',
- '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
- '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
- '../skia/skia.gyp:filter_fuzz_stub',
- '../skia/skia.gyp:image_operations_bench',
- '../sync/sync.gyp:run_sync_testserver',
- '../sync/sync.gyp:sync_endtoend_tests',
- '../sync/tools/sync_tools.gyp:sync_client',
- '../sync/tools/sync_tools.gyp:sync_listen_notifications',
- '../testing/gmock.gyp:gmock_main',
- '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
- '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
- '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+ '../remoting/app_remoting_webapp.gyp:ar_sample_app', # crbug.com/471916
+ ],
+ }],
+ ['test_isolation_mode!="noop"', {
+ 'dependencies': [
+ '../base/base.gyp:base_unittests_run',
+ '../cc/cc_tests.gyp:cc_unittests_run',
+ '../chrome/chrome.gyp:browser_tests_run',
+ '../chrome/chrome.gyp:chrome_run',
+ '../chrome/chrome.gyp:interactive_ui_tests_run',
+ '../chrome/chrome.gyp:sync_integration_tests_run',
+ '../chrome/chrome.gyp:unit_tests_run',
+ '../components/components_tests.gyp:components_browsertests_run',
+ '../components/components_tests.gyp:components_unittests_run',
+ '../content/content_shell_and_tests.gyp:content_browsertests_run',
+ '../content/content_shell_and_tests.gyp:content_unittests_run',
+ '../crypto/crypto.gyp:crypto_unittests_run',
+ '../courgette/courgette.gyp:courgette_unittests_run',
+ '../gpu/gpu.gyp:gpu_unittests_run',
+ '../media/cast/cast.gyp:cast_unittests_run',
+ '../media/media.gyp:media_unittests_run',
+ '../net/net.gyp:net_unittests_run',
+ '../sql/sql.gyp:sql_unittests_run',
+ '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
+ '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
+ '../ui/app_list/app_list.gyp:app_list_unittests_run',
+ '../ui/events/events.gyp:events_unittests_run',
+ '../ui/message_center/message_center.gyp:message_center_unittests_run',
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
+ ],
+ }],
+ ['test_isolation_mode!="noop" and use_ash==1', {
+ 'dependencies': [
+ '../ash/ash.gyp:ash_unittests_run',
+ ],
+ }],
+ ['test_isolation_mode!="noop" and OS=="linux"', {
+ 'dependencies': [
+ '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
+ ],
+ }],
+ ['use_openssl==1', {
+ 'dependencies': [
+ # TODO(GYP): All of these targets still need to be converted.
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test',
+ '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests',
+ ],
+ }],
+ ['chromeos==1', {
+ 'dependencies': [
+ '../content/content_shell_and_tests.gyp:video_encode_accelerator_unittest',
+ ],
+ }],
+ ['chromeos==1 and target_arch != "arm"', {
+ 'dependencies': [
+ '../content/content_shell_and_tests.gyp:vaapi_jpeg_decoder_unittest',
+ ],
+ }],
+ ['chromeos==1 or OS=="win" or OS=="android"', {
+ 'dependencies': [
+ '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest',
+ ],
+ }],
+ ['OS=="linux" or OS=="win"', {
+ 'dependencies': [
+ # TODO(GYP): Figure out which of these run on android/mac/win/ios/etc.
+ '../net/net.gyp:net_docs',
+ '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+
+ # TODO(GYP): in progress - see tfarina.
'../third_party/webrtc/tools/tools.gyp:frame_analyzer',
'../third_party/webrtc/tools/tools.gyp:rgba_to_i420_converter',
- '../tools/gn/gn.gyp:generate_test_gn_data',
- '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
- #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ?
- '../ui/compositor/compositor.gyp:compositor_unittests',
- '../ui/message_center/message_center.gyp:message_center_unittests',
- '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
- '../v8/tools/gyp/v8.gyp:v8_snapshot',
- '../v8/tools/gyp/v8.gyp:postmortem-metadata',
-
- # TODO(GYP) - list all of the examples explicitly.
- '../ppapi/ppapi_internal.gyp:*',
],
- 'conditions': [
- ['disable_nacl==0 and disable_nacl_untrusted==0', {
- 'dependencies': [
- '../components/nacl.gyp:nacl_loader_unittests',
- '../mojo/mojo_nacl.gyp:monacl_shell', # TODO(GYP) This will be deleted; don't port
- '../remoting/remoting.gyp:remoting_key_tester',
- ]
- }],
- ['chromeos== 1 or use_ash==1', {
- 'dependencies': [
- '../components/components.gyp:session_manager_component',
- ],
- }],
- ['use_x11==1', {
- 'dependencies': [
- '../gpu/tools/tools.gyp:compositor_model_bench',
- '../media/media.gyp:player_x11',
- ],
- }],
- ['remoting==1', {
- 'dependencies': [
- '../remoting/app_remoting_webapp.gyp:ar_sample_app',
- '../remoting/remoting.gyp:remoting_host',
- '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
- '../remoting/remoting.gyp:remoting_key_tester',
- '../remoting/remoting.gyp:remoting_me2me_host',
- '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
- '../remoting/remoting.gyp:remoting_native_messaging_manifests',
- '../remoting/remoting.gyp:remoting_perftests',
- '../remoting/remoting.gyp:remoting_start_host',
- '../remoting/remoting.gyp:remoting_unittests',
- ],
- }],
- ['toolkit_views==1', {
- 'dependencies': [
- '../ui/app_list/app_list.gyp:app_list_demo',
- ],
- }],
- ['test_isolation_mode!="noop"', {
- 'dependencies': [
- '../base/base.gyp:base_unittests_run',
- '../cc/cc_tests.gyp:cc_unittests_run',
- '../chrome/chrome.gyp:browser_tests_run',
- '../chrome/chrome.gyp:chrome_run',
- '../chrome/chrome.gyp:interactive_ui_tests_run',
- '../chrome/chrome.gyp:sync_integration_tests_run',
- '../chrome/chrome.gyp:unit_tests_run',
- '../components/components_tests.gyp:components_browsertests_run',
- '../components/components_tests.gyp:components_unittests_run',
- '../content/content_shell_and_tests.gyp:content_browsertests_run',
- '../content/content_shell_and_tests.gyp:content_unittests_run',
- '../crypto/crypto.gyp:crypto_unittests_run',
- '../courgette/courgette.gyp:courgette_unittests_run',
- '../gpu/gpu.gyp:gpu_unittests_run',
- '../media/cast/cast.gyp:cast_unittests_run',
- '../media/media.gyp:media_unittests_run',
- '../net/net.gyp:net_unittests_run',
- '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
- '../sql/sql.gyp:sql_unittests_run',
- '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
- '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
- '../ui/app_list/app_list.gyp:app_list_unittests_run',
- '../ui/events/events.gyp:events_unittests_run',
- '../ui/message_center/message_center.gyp:message_center_unittests_run',
- '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
- ],
- 'conditions': [
- ['use_ash==1', {
- 'dependencies': [
- '../ash/ash.gyp:ash_unittests_run',
- ],
- }],
- ],
- }],
+ }],
+ ['OS=="win"', {
+ 'dependencies': [
+ # TODO(GYP): All of these targets still need to be converted.
+ '../base/base.gyp:debug_message',
+ '../chrome/chrome.gyp:app_installer',
+ '../chrome/chrome.gyp:app_installer_unittests',
+ '../chrome/chrome.gyp:app_shim',
+ '../chrome/chrome.gyp:crash_service',
+ '../chrome/chrome.gyp:gcapi_dll',
+ '../chrome/chrome.gyp:gcapi_test',
+ '../chrome/chrome.gyp:installer_util_unittests',
+ '../chrome/chrome.gyp:pack_policy_templates',
+ '../chrome/chrome.gyp:sb_sigutil',
+ '../chrome/chrome.gyp:setup',
+ '../chrome/chrome.gyp:setup_unittests',
+ '../chrome/installer/mini_installer.gyp:mini_installer',
+ '../chrome/tools/crash_service/caps/caps.gyp:caps',
+ '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device',
+ '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device_unittests',
+ '../cloud_print/service/service.gyp:cloud_print_service',
+ '../cloud_print/service/service.gyp:cloud_print_service_config',
+ '../cloud_print/service/service.gyp:cloud_print_service_setup',
+ '../cloud_print/virtual_driver/win/install/virtual_driver_install.gyp:virtual_driver_setup',
+ '../cloud_print/virtual_driver/win/virtual_driver.gyp:gcp_portmon',
+ '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+ '../content/content_shell_and_tests.gyp:layout_test_helper',
+ '../gpu/gpu.gyp:angle_end2end_tests',
+ '../gpu/gpu.gyp:angle_perftests',
+ '../net/net.gyp:net_docs',
+ '../ppapi/ppapi_internal.gyp:ppapi_perftests',
+ '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+ '../remoting/remoting.gyp:remoting_breakpad_tester',
+ '../remoting/remoting.gyp:remoting_console',
+ '../remoting/remoting.gyp:remoting_desktop',
+ '../rlz/rlz.gyp:rlz',
+ '../tools/win/static_initializers/static_initializers.gyp:static_initializers',
],
}],
+ ['OS=="win" and win_use_allocator_shim==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator_unittests',
+ ]
+ }],
+ ['OS=="win" and target_arch=="ia32"', {
+ 'dependencies': [
+ # TODO(GYP): All of these targets need to be ported over.
+ '../base/base.gyp:base_win64',
+ '../base/base.gyp:base_i18n_nacl_win64',
+ '../chrome/chrome.gyp:crash_service_win64',
+ '../chrome/chrome.gyp:launcher_support64',
+ '../components/components.gyp:breakpad_win64',
+ '../courgette/courgette.gyp:courgette64',
+ '../crypto/crypto.gyp:crypto_nacl_win64',
+ '../ipc/ipc.gyp:ipc_win64',
+ '../sandbox/sandbox.gyp:sandbox_win64',
+ '../cloud_print/virtual_driver/win/virtual_driver64.gyp:gcp_portmon64',
+ '../cloud_print/virtual_driver/win/virtual_driver64.gyp:virtual_driver_lib64',
+ ],
+ }],
+ ['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
+ 'dependencies': [
+ # TODO(GYP): All of these targets need to be ported over.
+ '../components/components.gyp:policy_win64',
+ ]
+ }],
],
},
{
@@ -533,7 +673,6 @@
'type': 'none',
'dependencies': [
'All',
- 'aura_builder',
'blink_tests',
'chromium_builder_asan',
'chromium_builder_chromedriver',
@@ -543,6 +682,22 @@
'chromium_gpu_builder',
'chromium_gpu_debug_builder',
],
+ 'conditions': [
+ ['use_aura==1', {
+ 'dependencies': [
+ 'aura_builder',
+ ]
+ }],
+ ['OS=="win"', {
+ 'dependencies': [
+ 'chromium_builder',
+ 'chromium_builder_dbg_drmemory_win',
+ 'chromium_builder_nacl_sdk',
+ 'chromium_builder_lkgr_drmemory_win',
+ 'chromium_builder_dbg_tsan_win',
+ ],
+ }],
+ ],
},
]
}
diff --git a/build/grit_action.gypi b/build/grit_action.gypi
index 462fb4c..b24f0f8 100644
--- a/build/grit_action.gypi
+++ b/build/grit_action.gypi
@@ -50,11 +50,12 @@
],
'inputs': [
'<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
- '--inputs <(grit_grd_file) -f "<(grit_resource_ids)")',
+ '<@(grit_whitelist_flag) --inputs <(grit_grd_file) '
+ '-f "<(grit_resource_ids)")',
],
'outputs': [
'<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
- '--outputs \'<(grit_out_dir)\' '
+ '<@(grit_whitelist_flag) --outputs \'<(grit_out_dir)\' '
'<(grit_grd_file) -f "<(grit_resource_ids)")',
],
'action': ['<@(grit_cmd)',
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 45f3206..4ed15ba 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -30,9 +30,6 @@
# 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'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
sys.path.insert(1, os.path.join(chrome_src, 'chromecast', 'tools', 'build'))
sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build'))
@@ -42,6 +39,9 @@
sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
'Source', 'build', 'scripts'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
# On Windows, Psyco shortens warm runs of build/gyp_chromium by about
# 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
index 9be2b9e..c840f2d 100644
--- a/build/gyp_helper.py
+++ b/build/gyp_helper.py
@@ -25,10 +25,12 @@
supported_vars = (
'CC',
'CC_wrapper',
+ 'CC.host_wrapper',
'CHROMIUM_GYP_FILE',
'CHROMIUM_GYP_SYNTAX_CHECK',
'CXX',
'CXX_wrapper',
+ 'CXX.host_wrapper',
'GYP_DEFINES',
'GYP_GENERATOR_FLAGS',
'GYP_CROSSCOMPILE',
diff --git a/build/host_jar.gypi b/build/host_jar.gypi
index 6ccc1bd..9c35177 100644
--- a/build/host_jar.gypi
+++ b/build/host_jar.gypi
@@ -3,7 +3,9 @@
# found in the LICENSE file.
# This file is meant to be included into a target to provide a rule to build
-# a JAR file for use on a host in a consistent manner.
+# a JAR file for use on a host in a consistent manner. If a main class is
+# specified, this file will also generate an executable to run the jar in the
+# output folder's /bin/ directory.
#
# To use this, create a gyp target with the following form:
# {
@@ -69,9 +71,9 @@
'java_sources!': ['<!@(find <@(excluded_src_paths) -name "*.java")']
}],
['"<(jar_excluded_classes)" != ""', {
- 'extra_options': ['--excluded-classes=<(jar_excluded_classes)']
+ 'extra_options': ['--jar-excluded-classes=<(jar_excluded_classes)']
}],
- ['">(main_class)" != ""', {
+ ['main_class != ""', {
'extra_options': ['--main-class=>(main_class)']
}]
],
@@ -97,6 +99,33 @@
'^@(java_sources)',
],
},
+ ],
+ 'conditions': [
+ ['main_class != ""', {
+ 'actions': [
+ {
+ 'action_name': 'create_java_binary_script_<(_target_name)',
+ 'message': 'Creating java binary script <(_target_name)',
+ 'variables': {
+ 'output': '<(PRODUCT_DIR)/bin/<(_target_name)',
+ },
+ 'inputs': [
+ '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+ '<(jar_path)',
+ ],
+ 'outputs': [
+ '<(output)',
+ ],
+ 'action': [
+ 'python', '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+ '--classpath=>(input_jars_paths)',
+ '--jar-path=<(jar_path)',
+ '--output=<(output)',
+ '--main-class=>(main_class)',
+ ]
+ }
+ ]
+ }]
]
}
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index 53d9712..6473794 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -155,6 +155,12 @@
linux-libc-dev-armhf-cross
g++-arm-linux-gnueabihf"
+# Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056
+if [ "x$lsb_release" = "xtrusty" ]; then
+ arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf
+ gcc-4.8-multilib-arm-linux-gnueabihf"
+fi
+
# Packages to build NaCl, its toolchains, and its ports.
naclports_list="ant autoconf bison cmake gawk intltool xutils-dev xsltproc"
nacl_list="g++-mingw-w64-i686 lib32z1-dev
@@ -360,7 +366,7 @@
sudo dpkg --add-architecture i386
fi
fi
-#sudo apt-get update
+sudo apt-get update
# We initially run "apt-get" with the --reinstall option and parse its output.
# This way, we can find all the packages that need to be newly installed
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 28407eb..18239b7 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -17,10 +17,12 @@
IDR_DEFAULT_FAVICON_32
IDR_DEFAULT_FAVICON_64
IDR_DIR_HEADER_HTML
+IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL
IDR_DISTILLER_CSS
IDR_DISTILLER_JS
IDR_DOM_DISTILLER_VIEWER_HTML
IDR_DOM_DISTILLER_VIEWER_JS
+IDR_EXTRACT_PAGE_FEATURES_JS
IDR_FLAGS_FAVICON
IDR_FLAGS_HTML
IDR_FLAGS_JS
@@ -98,7 +100,8 @@
IDR_TOOLBAR_SHADOW_FULL_BLEED
IDR_TRANSLATE_JS
IDR_UBER_UTILS_JS
-IDR_WEBUI_I18N_TEMPLATE2_JS
+IDR_WEBUI_I18N_TEMPLATE_JS
+IDR_WEBUI_I18N_TEMPLATE_POLYMER_JS
IDR_WEBUI_JSTEMPLATE_JS
IDR_WEBUI_JS_LOAD_TIME_DATA
IDS_ABOUT_MAC
@@ -304,6 +307,9 @@
IDS_DELETE
IDS_DISABLE_TOUCH_ADJUSTMENT_DESCRIPTION
IDS_DISABLE_TOUCH_ADJUSTMENT_NAME
+IDS_DOM_DISTILLER_QUALITY_ANSWER_NO
+IDS_DOM_DISTILLER_QUALITY_ANSWER_YES
+IDS_DOM_DISTILLER_QUALITY_QUESTION
IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT
IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE
IDS_DOM_DISTILLER_VIEWER_LOADING_STRING
@@ -348,6 +354,7 @@
IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT
IDS_ERRORPAGES_DETAILS_GONE
IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED
+IDS_ERRORPAGES_DETAILS_ICANN_NAME_COLLISION
IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR
IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED
IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED
@@ -426,6 +433,7 @@
IDS_ERRORPAGES_SUMMARY_FORBIDDEN
IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT
IDS_ERRORPAGES_SUMMARY_GONE
+IDS_ERRORPAGES_SUMMARY_ICANN_NAME_COLLISION
IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR
IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED
IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_INSTRUCTIONS_TEMPLATE
@@ -514,8 +522,6 @@
IDS_FLAGS_ENABLE
IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_DESCRIPTION
IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_NAME
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING_DESCRIPTION
IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH
IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH_DESCRIPTION
IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION
@@ -530,6 +536,8 @@
IDS_FLAGS_ENABLE_EXPERIMENTAL_CANVAS_FEATURES_NAME
IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_DESCRIPTION
IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_NAME
+IDS_FLAGS_ENABLE_ICON_NTP_DESCRIPTION
+IDS_FLAGS_ENABLE_ICON_NTP_NAME
IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_DESCRIPTION
IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_NAME
IDS_FLAGS_ENABLE_NACL_DEBUG_DESCRIPTION
@@ -762,8 +770,6 @@
IDS_NUMBERED_PROFILE_NAME
IDS_OK
IDS_OMNIBOX_EMPTY_HINT
-IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER
-IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER
IDS_ONE_CLICK_SIGNIN_CONFIRM_EMAIL_DIALOG_CANCEL_BUTTON
IDS_OPEN_TABS_NOTYETSYNCED
IDS_OPEN_TABS_PROMOCOMPUTER
@@ -852,8 +858,11 @@
IDS_POLICY_INVALID_BOOKMARK
IDS_POLICY_INVALID_PROXY_MODE_ERROR
IDS_POLICY_INVALID_SEARCH_URL_ERROR
+IDS_POLICY_LABEL_ASSET_ID
IDS_POLICY_LABEL_CLIENT_ID
+IDS_POLICY_LABEL_DIRECTORY_API_ID
IDS_POLICY_LABEL_DOMAIN
+IDS_POLICY_LABEL_LOCATION
IDS_POLICY_LABEL_REFRESH_INTERVAL
IDS_POLICY_LABEL_STATUS
IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH
@@ -863,6 +872,7 @@
IDS_POLICY_LEVEL_RECOMMENDED
IDS_POLICY_LIST_ENTRY_ERROR
IDS_POLICY_NEVER_FETCHED
+IDS_POLICY_NOT_SPECIFIED
IDS_POLICY_NOT_SPECIFIED_ERROR
IDS_POLICY_NO_POLICIES_SET
IDS_POLICY_OK
@@ -979,6 +989,7 @@
IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE_V2
IDS_SAFE_BROWSING_PRIVACY_POLICY_URL
IDS_SAVE
+IDS_SEARCH_BOX_EMPTY_HINT
IDS_SECURE_CONNECTION_EV
IDS_SESSION_CRASHED_VIEW_MESSAGE
IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON
@@ -1078,138 +1089,28 @@
IDS_SYNC_UPGRADE_CLIENT
IDS_SYSTEM_FLAGS_OWNER_ONLY
IDS_TERMS_HTML
-IDS_TIME_DAYS_1ST_DEFAULT
-IDS_TIME_DAYS_1ST_FEW
-IDS_TIME_DAYS_1ST_MANY
-IDS_TIME_DAYS_1ST_SINGULAR
-IDS_TIME_DAYS_1ST_TWO
-IDS_TIME_DAYS_1ST_ZERO
-IDS_TIME_DAYS_DEFAULT
-IDS_TIME_DAYS_FEW
-IDS_TIME_DAYS_MANY
-IDS_TIME_DAYS_SINGULAR
-IDS_TIME_DAYS_TWO
-IDS_TIME_DAYS_ZERO
-IDS_TIME_ELAPSED_DAYS_DEFAULT
-IDS_TIME_ELAPSED_DAYS_FEW
-IDS_TIME_ELAPSED_DAYS_MANY
-IDS_TIME_ELAPSED_DAYS_SINGULAR
-IDS_TIME_ELAPSED_DAYS_TWO
-IDS_TIME_ELAPSED_DAYS_ZERO
-IDS_TIME_ELAPSED_HOURS_DEFAULT
-IDS_TIME_ELAPSED_HOURS_FEW
-IDS_TIME_ELAPSED_HOURS_MANY
-IDS_TIME_ELAPSED_HOURS_SINGULAR
-IDS_TIME_ELAPSED_HOURS_TWO
-IDS_TIME_ELAPSED_HOURS_ZERO
-IDS_TIME_ELAPSED_MINS_DEFAULT
-IDS_TIME_ELAPSED_MINS_FEW
-IDS_TIME_ELAPSED_MINS_MANY
-IDS_TIME_ELAPSED_MINS_SINGULAR
-IDS_TIME_ELAPSED_MINS_TWO
-IDS_TIME_ELAPSED_MINS_ZERO
-IDS_TIME_ELAPSED_SECS_DEFAULT
-IDS_TIME_ELAPSED_SECS_FEW
-IDS_TIME_ELAPSED_SECS_MANY
-IDS_TIME_ELAPSED_SECS_SINGULAR
-IDS_TIME_ELAPSED_SECS_TWO
-IDS_TIME_ELAPSED_SECS_ZERO
-IDS_TIME_HOURS_1ST_DEFAULT
-IDS_TIME_HOURS_1ST_FEW
-IDS_TIME_HOURS_1ST_MANY
-IDS_TIME_HOURS_1ST_SINGULAR
-IDS_TIME_HOURS_1ST_TWO
-IDS_TIME_HOURS_1ST_ZERO
-IDS_TIME_HOURS_2ND_DEFAULT
-IDS_TIME_HOURS_2ND_FEW
-IDS_TIME_HOURS_2ND_MANY
-IDS_TIME_HOURS_2ND_SINGULAR
-IDS_TIME_HOURS_2ND_TWO
-IDS_TIME_HOURS_2ND_ZERO
-IDS_TIME_HOURS_DEFAULT
-IDS_TIME_HOURS_FEW
-IDS_TIME_HOURS_MANY
-IDS_TIME_HOURS_SINGULAR
-IDS_TIME_HOURS_TWO
-IDS_TIME_HOURS_ZERO
-IDS_TIME_LONG_MINS_1ST_DEFAULT
-IDS_TIME_LONG_MINS_1ST_FEW
-IDS_TIME_LONG_MINS_1ST_MANY
-IDS_TIME_LONG_MINS_1ST_SINGULAR
-IDS_TIME_LONG_MINS_1ST_TWO
-IDS_TIME_LONG_MINS_1ST_ZERO
-IDS_TIME_LONG_MINS_2ND_DEFAULT
-IDS_TIME_LONG_MINS_2ND_FEW
-IDS_TIME_LONG_MINS_2ND_MANY
-IDS_TIME_LONG_MINS_2ND_SINGULAR
-IDS_TIME_LONG_MINS_2ND_TWO
-IDS_TIME_LONG_MINS_2ND_ZERO
-IDS_TIME_LONG_MINS_DEFAULT
-IDS_TIME_LONG_MINS_FEW
-IDS_TIME_LONG_MINS_MANY
-IDS_TIME_LONG_MINS_SINGULAR
-IDS_TIME_LONG_MINS_TWO
-IDS_TIME_LONG_MINS_ZERO
-IDS_TIME_LONG_SECS_2ND_DEFAULT
-IDS_TIME_LONG_SECS_2ND_FEW
-IDS_TIME_LONG_SECS_2ND_MANY
-IDS_TIME_LONG_SECS_2ND_SINGULAR
-IDS_TIME_LONG_SECS_2ND_TWO
-IDS_TIME_LONG_SECS_2ND_ZERO
-IDS_TIME_LONG_SECS_DEFAULT
-IDS_TIME_LONG_SECS_FEW
-IDS_TIME_LONG_SECS_MANY
-IDS_TIME_LONG_SECS_SINGULAR
-IDS_TIME_LONG_SECS_TWO
-IDS_TIME_LONG_SECS_ZERO
-IDS_TIME_MINS_DEFAULT
-IDS_TIME_MINS_FEW
-IDS_TIME_MINS_MANY
-IDS_TIME_MINS_SINGULAR
-IDS_TIME_MINS_TWO
-IDS_TIME_MINS_ZERO
-IDS_TIME_REMAINING_DAYS_DEFAULT
-IDS_TIME_REMAINING_DAYS_FEW
-IDS_TIME_REMAINING_DAYS_MANY
-IDS_TIME_REMAINING_DAYS_SINGULAR
-IDS_TIME_REMAINING_DAYS_TWO
-IDS_TIME_REMAINING_DAYS_ZERO
-IDS_TIME_REMAINING_HOURS_DEFAULT
-IDS_TIME_REMAINING_HOURS_FEW
-IDS_TIME_REMAINING_HOURS_MANY
-IDS_TIME_REMAINING_HOURS_SINGULAR
-IDS_TIME_REMAINING_HOURS_TWO
-IDS_TIME_REMAINING_HOURS_ZERO
-IDS_TIME_REMAINING_LONG_MINS_DEFAULT
-IDS_TIME_REMAINING_LONG_MINS_FEW
-IDS_TIME_REMAINING_LONG_MINS_MANY
-IDS_TIME_REMAINING_LONG_MINS_SINGULAR
-IDS_TIME_REMAINING_LONG_MINS_TWO
-IDS_TIME_REMAINING_LONG_MINS_ZERO
-IDS_TIME_REMAINING_LONG_SECS_DEFAULT
-IDS_TIME_REMAINING_LONG_SECS_FEW
-IDS_TIME_REMAINING_LONG_SECS_MANY
-IDS_TIME_REMAINING_LONG_SECS_SINGULAR
-IDS_TIME_REMAINING_LONG_SECS_TWO
-IDS_TIME_REMAINING_LONG_SECS_ZERO
-IDS_TIME_REMAINING_MINS_DEFAULT
-IDS_TIME_REMAINING_MINS_FEW
-IDS_TIME_REMAINING_MINS_MANY
-IDS_TIME_REMAINING_MINS_SINGULAR
-IDS_TIME_REMAINING_MINS_TWO
-IDS_TIME_REMAINING_MINS_ZERO
-IDS_TIME_REMAINING_SECS_DEFAULT
-IDS_TIME_REMAINING_SECS_FEW
-IDS_TIME_REMAINING_SECS_MANY
-IDS_TIME_REMAINING_SECS_SINGULAR
-IDS_TIME_REMAINING_SECS_TWO
-IDS_TIME_REMAINING_SECS_ZERO
-IDS_TIME_SECS_DEFAULT
-IDS_TIME_SECS_FEW
-IDS_TIME_SECS_MANY
-IDS_TIME_SECS_SINGULAR
-IDS_TIME_SECS_TWO
-IDS_TIME_SECS_ZERO
+IDS_TIME_DAYS
+IDS_TIME_DAYS_1ST
+IDS_TIME_ELAPSED_DAYS
+IDS_TIME_ELAPSED_HOURS
+IDS_TIME_ELAPSED_MINS
+IDS_TIME_ELAPSED_SECS
+IDS_TIME_HOURS
+IDS_TIME_HOURS_1ST
+IDS_TIME_HOURS_2ND
+IDS_TIME_LONG_MINS
+IDS_TIME_LONG_MINS_1ST
+IDS_TIME_LONG_MINS_2ND
+IDS_TIME_LONG_SECS
+IDS_TIME_LONG_SECS_2ND
+IDS_TIME_MINS
+IDS_TIME_REMAINING_DAYS
+IDS_TIME_REMAINING_HOURS
+IDS_TIME_REMAINING_LONG_MINS
+IDS_TIME_REMAINING_LONG_SECS
+IDS_TIME_REMAINING_MINS
+IDS_TIME_REMAINING_SECS
+IDS_TIME_SECS
IDS_TOOLTIP_STAR
IDS_TOUCH_EVENTS_DESCRIPTION
IDS_TOUCH_EVENTS_NAME
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 5fa1e67..7b050e2 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -61,9 +61,6 @@
# Variables should use the -V FOO=<(FOO) form so frequent values,
# like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help' for
# more details.
- #
- # This list needs to be kept in sync with the cmd line options
- # in src/build/android/pylib/gtest/setup.py.
# Path variables are used to replace file paths when loading a .isolate
# file
@@ -74,12 +71,17 @@
# the .isolate file but are not considered relative paths.
'--extra-variable', 'version_full=<(version_full)',
+ # Note: This list must match DefaultConfigVariables()
+ # in build/android/pylib/utils/isolator.py
'--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
'--config-variable', 'OS=<(OS)',
'--config-variable', 'asan=<(asan)',
+ '--config-variable', 'branding=<(branding)',
'--config-variable', 'chromeos=<(chromeos)',
'--config-variable', 'component=<(component)',
'--config-variable', 'disable_nacl=<(disable_nacl)',
+ '--config-variable', 'enable_pepper_cdms=<(enable_pepper_cdms)',
+ '--config-variable', 'enable_plugins=<(enable_plugins)',
'--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
@@ -93,6 +95,8 @@
'--config-variable', 'tsan=<(tsan)',
'--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
'--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+ '--config-variable',
+ 'use_prebuilt_instrumented_libraries=<(use_prebuilt_instrumented_libraries)',
'--config-variable', 'use_openssl=<(use_openssl)',
'--config-variable', 'use_ozone=<(use_ozone)',
'--config-variable', 'use_x11=<(use_x11)',
diff --git a/build/jar_file_jni_generator.gypi b/build/jar_file_jni_generator.gypi
index 6f5d2f1..3d95b28 100644
--- a/build/jar_file_jni_generator.gypi
+++ b/build/jar_file_jni_generator.gypi
@@ -64,14 +64,4 @@
# This target exports a hard dependency because it generates header
# files.
'hard_dependency': 1,
- 'conditions': [
- ['android_webview_build==1', {
- 'variables': {
- 'native_exports%': '--native_exports',
- },
- 'dependencies': [
- '<(DEPTH)/build/android/android_exports.gyp:android_exports',
- ],
- }],
- ],
}
diff --git a/build/java.gypi b/build/java.gypi
index 061dff2..730fa22 100644
--- a/build/java.gypi
+++ b/build/java.gypi
@@ -77,6 +77,8 @@
'lint_result': '<(intermediate_dir)/lint_result.xml',
'lint_config': '<(intermediate_dir)/lint_config.xml',
'never_lint%': 0,
+ 'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+ 'run_findbugs%': 0,
'proguard_config%': '',
'proguard_preprocess%': '0',
'variables': {
@@ -217,6 +219,31 @@
},
],
}],
+ ['run_findbugs == 1', {
+ 'actions': [
+ {
+ 'action_name': 'findbugs_<(_target_name)',
+ 'message': 'Running findbugs on <(_target_name)',
+ 'inputs': [
+ '<(DEPTH)/build/android/findbugs_diff.py',
+ '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+ '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+ '>@(input_jars_paths)',
+ '<(jar_final_path)',
+ '<(compile_stamp)',
+ ],
+ 'outputs': [
+ '<(findbugs_stamp)',
+ ],
+ 'action': [
+ 'python', '<(DEPTH)/build/android/findbugs_diff.py',
+ '--auxclasspath-gyp', '>(input_jars_paths)',
+ '--stamp', '<(findbugs_stamp)',
+ '<(jar_final_path)',
+ ],
+ },
+ ],
+ }],
],
'actions': [
{
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index c5e7ae3..56aefdf 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -103,6 +103,8 @@
'lint_result': '<(intermediate_dir)/lint_result.xml',
'lint_config': '<(intermediate_dir)/lint_config.xml',
'never_lint%': 0,
+ 'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+ 'run_findbugs%': 0,
'java_in_dir_suffix%': '/src',
'instr_stamp': '<(intermediate_dir)/instr.stamp',
'jar_stamp': '<(intermediate_dir)/jar.stamp',
@@ -558,6 +560,32 @@
'<(DEPTH)/tools/android/android_tools.gyp:android_tools',
]
}],
+ ['run_findbugs == 1', {
+ 'actions': [
+ {
+ 'action_name': 'findbugs_<(_target_name)',
+ 'message': 'Running findbugs on <(_target_name)',
+ 'inputs': [
+ '<(DEPTH)/build/android/findbugs_diff.py',
+ '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+ '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+ '>@(input_jars_paths)',
+ '<(jar_path)',
+ '<(compile_stamp)',
+ ],
+ 'outputs': [
+ '<(findbugs_stamp)',
+ ],
+ 'action': [
+ 'python', '<(DEPTH)/build/android/findbugs_diff.py',
+ '--auxclasspath-gyp', '>(input_jars_paths)',
+ '--stamp', '<(findbugs_stamp)',
+ '<(jar_path)',
+ ],
+ },
+ ],
+ },
+ ]
],
'dependencies': [
'<(DEPTH)/tools/android/md5sum/md5sum.gyp:md5sum',
diff --git a/build/jni_generator.gypi b/build/jni_generator.gypi
index c2c71e7..7a9e333 100644
--- a/build/jni_generator.gypi
+++ b/build/jni_generator.gypi
@@ -83,15 +83,5 @@
# This target exports a hard dependency because it generates header
# files.
'hard_dependency': 1,
- 'conditions': [
- ['android_webview_build==1', {
- 'variables': {
- 'native_exports%': '--native_exports',
- },
- 'dependencies': [
- '<(DEPTH)/build/android/android_exports.gyp:android_exports',
- ],
- }],
- ],
}
diff --git a/build/linux/install-arm-sysroot.py b/build/linux/install-arm-sysroot.py
deleted file mode 100755
index 495fc75..0000000
--- a/build/linux/install-arm-sysroot.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import sys
-
-msg = '''\
-ERROR: This script has merged with install-debian.wheezy.sysroot.py.
-Please use that instead (with --arch=arm).
-'''
-sys.stderr.write(msg)
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 5333798..476476e 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -1124,6 +1124,7 @@
'spd_set_synthesis_voice',
'spd_list_modules',
'spd_set_output_module',
+ 'spd_set_language',
],
'message': 'Generating libspeechd library loader',
'process_outputs_as_sources': 1,
@@ -1180,8 +1181,7 @@
'dependencies': [
'../../third_party/boringssl/boringssl.gyp:boringssl',
],
- }],
- ['use_openssl==0', {
+ }, {
'dependencies': [
'../../net/third_party/nss/ssl.gyp:libssl',
],
@@ -1191,6 +1191,13 @@
# before other includes, as we are shadowing system headers.
'<(DEPTH)/net/third_party/nss/ssl',
],
+ },
+ }],
+ # Link in the system NSS if it is used for either the internal
+ # crypto library (use_openssl==0) or platform certificate
+ # library (use_nss_certs==1).
+ ['use_openssl==0 or use_nss_certs==1', {
+ 'direct_dependent_settings': {
'cflags': [
'<!@(<(pkg-config) --cflags nss)',
],
@@ -1203,15 +1210,17 @@
'<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
],
},
- }],
- ['use_openssl==0 and clang==1', {
- 'direct_dependent_settings': {
- 'cflags': [
- # There is a broken header guard in /usr/include/nss/secmod.h:
- # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
- '-Wno-header-guard',
- ],
- },
+ 'conditions': [
+ ['clang==1', {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ # There is a broken header guard in /usr/include/nss/secmod.h:
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
+ '-Wno-header-guard',
+ ],
+ },
+ }],
+ ],
}],
]
}],
diff --git a/build/linux/unbundle/libvpx.gyp b/build/linux/unbundle/libvpx.gyp
index cdcf6fa..75671c5 100644
--- a/build/linux/unbundle/libvpx.gyp
+++ b/build/linux/unbundle/libvpx.gyp
@@ -14,16 +14,17 @@
'variables': {
'headers_root_path': 'source/libvpx',
'header_filenames': [
- 'vpx/vpx_codec_impl_bottom.h',
- 'vpx/vpx_image.h',
- 'vpx/vpx_decoder.h',
'vpx/vp8.h',
- 'vpx/vpx_codec.h',
- 'vpx/vpx_codec_impl_top.h',
'vpx/vp8cx.h',
- 'vpx/vpx_integer.h',
'vpx/vp8dx.h',
+ 'vpx/vpx_codec.h',
+ 'vpx/vpx_codec_impl_bottom.h',
+ 'vpx/vpx_codec_impl_top.h',
+ 'vpx/vpx_decoder.h',
'vpx/vpx_encoder.h',
+ 'vpx/vpx_frame_buffer.h',
+ 'vpx/vpx_image.h',
+ 'vpx/vpx_integer.h',
],
},
'includes': [
diff --git a/build/protoc_java.gypi b/build/protoc_java.gypi
index 9ed597b..6fd80d8 100644
--- a/build/protoc_java.gypi
+++ b/build/protoc_java.gypi
@@ -50,6 +50,7 @@
# Adding the |stamp_file| to |additional_input_paths| makes the actions in
# the include of java.gypi depend on the genproto_java action.
'additional_input_paths': ['<(stamp_file)'],
+ 'run_findbugs': 0,
},
'actions': [
{
diff --git a/build/sanitizers/asan_suppressions.cc b/build/sanitizers/asan_suppressions.cc
new file mode 100644
index 0000000..df94bc8
--- /dev/null
+++ b/build/sanitizers/asan_suppressions.cc
@@ -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.
+
+// This file contains the default suppressions for AddressSanitizer.
+// It should only be used under very limited circumstances such as suppressing
+// a report caused by an interceptor call in a system-installed library.
+
+#if defined(ADDRESS_SANITIZER)
+
+// Please make sure the code below declares a single string variable
+// kASanDefaultSuppressions which contains ASan suppressions delimited by
+// newlines.
+char kASanDefaultSuppressions[] =
+// http://crbug.com/178677
+"interceptor_via_lib:libsqlite3.so\n"
+
+// PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
+
+// End of suppressions.
+; // Please keep this semicolon.
+
+#endif // ADDRESS_SANITIZER
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc
index 33090fb..a659a22 100644
--- a/build/sanitizers/sanitizer_options.cc
+++ b/build/sanitizers/sanitizer_options.cc
@@ -36,8 +36,6 @@
#if defined(ADDRESS_SANITIZER)
// Default options for AddressSanitizer in various configurations:
-// strict_memcmp=1 - disable the strict memcmp() checking
-// (http://crbug.com/178677 and http://crbug.com/178404).
// malloc_context_size=5 - limit the size of stack traces collected by ASan
// for each malloc/free by 5 frames. These stack traces tend to accumulate
// very fast in applications using JIT (v8 in Chrome's case), see
@@ -52,8 +50,6 @@
// they reside in shared memory). This option is going to be deprecated in
// upstream AddressSanitizer and must not be used anywhere except the
// official builds.
-// replace_intrin=0 - do not intercept memcpy(), memmove() and memset() to
-// work around http://crbug.com/162461 (ASan report in OpenCL on Mac).
// check_printf=1 - check the memory accesses to printf (and other formatted
// output routines) arguments.
// use_sigaltstack=1 - handle signals on an alternate signal stack. Useful
@@ -66,32 +62,28 @@
// so the slow unwinder may not work properly.
// detect_stack_use_after_return=1 - use fake stack to delay the reuse of
// stack allocations and detect stack-use-after-return errors.
-// detect_container_overflow=0 - do not detect overflows in containers
-// until crbug.com/459632 is fixed.
#if defined(OS_LINUX)
#if defined(GOOGLE_CHROME_BUILD)
// Default AddressSanitizer options for the official build. These do not affect
// tests on buildbots (which don't set GOOGLE_CHROME_BUILD) or non-official
// Chromium builds.
const char kAsanDefaultOptions[] =
- "legacy_pthread_cond=1 malloc_context_size=5 strict_memcmp=0 "
+ "legacy_pthread_cond=1 malloc_context_size=5 "
"symbolize=false check_printf=1 use_sigaltstack=1 detect_leaks=0 "
- "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
- "detect_container_overflow=0 ";
+ "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1";
#else
// Default AddressSanitizer options for buildbots and non-official builds.
const char *kAsanDefaultOptions =
- "strict_memcmp=0 symbolize=false check_printf=1 use_sigaltstack=1 "
+ "symbolize=false check_printf=1 use_sigaltstack=1 "
"detect_leaks=0 strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
- "detect_stack_use_after_return=1 detect_container_overflow=0 ";
+ "detect_stack_use_after_return=1 ";
#endif // GOOGLE_CHROME_BUILD
#elif defined(OS_MACOSX)
const char *kAsanDefaultOptions =
- "strict_memcmp=0 replace_intrin=0 check_printf=1 use_sigaltstack=1 "
+ "check_printf=1 use_sigaltstack=1 "
"strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
- "detect_stack_use_after_return=1 detect_odr_violation=0 "
- "detect_container_overflow=0 ";
+ "detect_stack_use_after_return=1 detect_odr_violation=0 ";
static const char kNaClDefaultOptions[] = "handle_segv=0";
static const char kNaClFlag[] = "--type=nacl-loader";
#endif // OS_LINUX
@@ -112,6 +104,12 @@
#endif
return kAsanDefaultOptions;
}
+
+extern "C" char kASanDefaultSuppressions[];
+
+SANITIZER_HOOK_ATTRIBUTE const char *__asan_default_suppressions() {
+ return kASanDefaultSuppressions;
+}
#endif // OS_LINUX || OS_MACOSX
#endif // ADDRESS_SANITIZER
diff --git a/build/sanitizers/sanitizers.gyp b/build/sanitizers/sanitizers.gyp
index 4126d22..91dab8a 100644
--- a/build/sanitizers/sanitizers.gyp
+++ b/build/sanitizers/sanitizers.gyp
@@ -41,6 +41,11 @@
'lsan_suppressions.cc',
],
}],
+ ['asan==1', {
+ 'sources': [
+ 'asan_suppressions.cc',
+ ],
+ }],
],
'cflags/': [
['exclude', '-fsanitize='],
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 76d2e1e..352b41f 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -63,6 +63,7 @@
// http://crbug.com/158922
"race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"
+"race:third_party/libvpx/source/libvpx/vp9/encoder/*\n"
// http://crbug.com/189177
"race:thread_manager\n"
@@ -100,9 +101,6 @@
// http://crbug.com/246968
"race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"
-// http://crbug.com/246970
-"race:webrtc::EventPosix::StartTimer\n"
-
// http://crbug.com/246974
"race:content::GpuWatchdogThread::CheckArmed\n"
@@ -124,12 +122,12 @@
"race:base::PowerMonitor::RemoveObserver\n"
"race:base::PowerMonitor::IsOnBatteryPower\n"
+// http://crbug.com/258935
+"race:base::Thread::StopSoon\n"
+
// http://crbug.com/268941
"race:tracked_objects::ThreadData::tls_index_\n"
-// http://crbug.com/270037
-"race:gLibCleanupFunctions\n"
-
// http://crbug.com/272095
"race:base::g_top_manager\n"
@@ -241,9 +239,6 @@
// http://crbug.com/363999
"race:v8::internal::EnterDebugger::*EnterDebugger\n"
-// http://crbug.com/364006
-"race:gfx::ImageFamily::~ImageFamily\n"
-
// https://code.google.com/p/v8/issues/detail?id=3143
"race:v8::internal::FLAG_track_double_fields\n"
@@ -290,9 +285,6 @@
// http://crbug.com/425057
"deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
-// https://crbug.com/433993
-"deadlock:content::WebRtcAudioDeviceImpl\n"
-
// http://crbug.com/417193
// Suppressing both AudioContext.{cpp,h}.
"race:modules/webaudio/AudioContext\n"
@@ -303,6 +295,9 @@
// https://crbug.com/430533
"race:TileTaskGraphRunner::Run\n"
+// https://crbug.com/437044
+"race:SkEventTracer\n"
+
// https://crbug.com/448203
"race:blink::RemoteFrame::detach\n"
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index 92a088a..099b892 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -9,7 +9,7 @@
}
# This is the GN version of
-# //build/android/cpufeatures.gypi:cpufeatures
+# //build/android/ndk.gyp:cpu_features
source_set("cpu_features") {
sources = [
"ndk/sources/android/cpufeatures/cpu-features.c",
@@ -65,6 +65,13 @@
jar_path = "$android_sdk_root/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar"
}
+android_java_prebuilt("android_support_v7_recyclerview_java") {
+ deps = [
+ ":android_support_v7_appcompat_java",
+ ]
+ jar_path = "$android_sdk_root/extras/android/support/v7/recyclerview/libs/android-support-v7-recyclerview.jar"
+}
+
android_resources("google_play_services_default_resources") {
v14_verify_only = true
resource_dirs = [ "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/res" ]
diff --git a/build/secondary/third_party/leveldatabase/BUILD.gn b/build/secondary/third_party/leveldatabase/BUILD.gn
deleted file mode 100644
index 067af30..0000000
--- a/build/secondary/third_party/leveldatabase/BUILD.gn
+++ /dev/null
@@ -1,338 +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.
-
-# Snappy is a compression library we use.
-# TODO(brettw) It's not clear why this needs to be parameterized.
-
-import("//testing/test.gni")
-
-use_snappy = true
-
-defines = [ "LEVELDB_PLATFORM_CHROMIUM=1" ]
-
-config("leveldatabase_config") {
- include_dirs = [
- ".",
- "src",
- "src/include",
- ]
-}
-
-static_library("leveldatabase") {
- sources = [
- "env_chromium.cc",
- "env_chromium.h",
- "env_idb.h",
- "port/port_chromium.cc",
- "port/port_chromium.h",
- "src/db/builder.cc",
- "src/db/builder.h",
- "src/db/db_impl.cc",
- "src/db/db_impl.h",
- "src/db/db_iter.cc",
- "src/db/db_iter.h",
- "src/db/dbformat.cc",
- "src/db/dbformat.h",
- "src/db/filename.cc",
- "src/db/filename.h",
- "src/db/log_format.h",
- "src/db/log_reader.cc",
- "src/db/log_reader.h",
- "src/db/log_writer.cc",
- "src/db/log_writer.h",
- "src/db/memtable.cc",
- "src/db/memtable.h",
- "src/db/repair.cc",
- "src/db/skiplist.h",
- "src/db/snapshot.h",
- "src/db/table_cache.cc",
- "src/db/table_cache.h",
- "src/db/version_edit.cc",
- "src/db/version_edit.h",
- "src/db/version_set.cc",
- "src/db/version_set.h",
- "src/db/write_batch.cc",
- "src/db/write_batch_internal.h",
- "src/helpers/memenv/memenv.cc",
- "src/helpers/memenv/memenv.h",
- "src/include/leveldb/cache.h",
- "src/include/leveldb/comparator.h",
- "src/include/leveldb/db.h",
- "src/include/leveldb/env.h",
- "src/include/leveldb/filter_policy.h",
- "src/include/leveldb/iterator.h",
- "src/include/leveldb/options.h",
- "src/include/leveldb/slice.h",
- "src/include/leveldb/status.h",
- "src/include/leveldb/table.h",
- "src/include/leveldb/table_builder.h",
- "src/include/leveldb/write_batch.h",
- "src/port/port.h",
- "src/port/port_example.h",
-
- #"src/port/port_posix.cc", # We use the chromium port instead of this.
- #"src/port/port_posix.h",
- "src/table/block.cc",
- "src/table/block.h",
- "src/table/block_builder.cc",
- "src/table/block_builder.h",
- "src/table/filter_block.cc",
- "src/table/filter_block.h",
- "src/table/format.cc",
- "src/table/format.h",
- "src/table/iterator.cc",
- "src/table/iterator_wrapper.h",
- "src/table/merger.cc",
- "src/table/merger.h",
- "src/table/table.cc",
- "src/table/table_builder.cc",
- "src/table/two_level_iterator.cc",
- "src/table/two_level_iterator.h",
- "src/util/arena.cc",
- "src/util/arena.h",
- "src/util/bloom.cc",
- "src/util/cache.cc",
- "src/util/coding.cc",
- "src/util/coding.h",
- "src/util/comparator.cc",
- "src/util/crc32c.cc",
- "src/util/crc32c.h",
- "src/util/env.cc",
- "src/util/filter_policy.cc",
- "src/util/hash.cc",
- "src/util/hash.h",
- "src/util/logging.cc",
- "src/util/logging.h",
- "src/util/mutexlock.h",
- "src/util/options.cc",
- "src/util/random.h",
- "src/util/status.cc",
- ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-
- public_configs = [ ":leveldatabase_config" ]
-
- deps = [
- "//base",
- "//base/third_party/dynamic_annotations",
- "//third_party/re2",
- ]
-
- if (use_snappy) {
- defines += [ "USE_SNAPPY=1" ]
- deps += [ "//third_party/snappy" ]
- }
-}
-
-if (!is_android) {
- test("env_chromium_unittests") {
- sources = [
- "env_chromium_unittest.cc",
- ]
- deps = [
- ":leveldatabase",
- "//base/test:test_support",
- "//testing/gtest",
- ]
- }
-
- static_library("leveldb_testutil") {
- sources = [
- "src/util/histogram.cc",
- "src/util/histogram.h",
- "src/util/testharness.cc",
- "src/util/testharness.h",
- "src/util/testutil.cc",
- "src/util/testutil.h",
- ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-
- public_deps = [
- ":leveldatabase",
- ]
- deps = [
- "//base",
- ]
- }
-
- test("leveldb_arena_test") {
- sources = [
- "src/util/arena_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_bloom_test") {
- sources = [
- "src/util/bloom_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_cache_test") {
- sources = [
- "src/util/cache_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_corruption_test") {
- sources = [
- "src/db/corruption_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_crc32c_test") {
- sources = [
- "src/util/crc32c_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_db_bench") {
- sources = [
- "src/db/db_bench.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_db_test") {
- sources = [
- "src/db/db_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_dbformat_test") {
- sources = [
- "src/db/dbformat_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_env_test") {
- sources = [
- "src/util/env_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_filename_test") {
- sources = [
- "src/db/filename_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_filter_block_test") {
- sources = [
- "src/table/filter_block_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_log_test") {
- sources = [
- "src/db/log_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_skiplist_test") {
- sources = [
- "src/db/skiplist_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_table_test") {
- sources = [
- "src/table/table_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_version_edit_test") {
- sources = [
- "src/db/version_edit_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-
- test("leveldb_write_batch_test") {
- sources = [
- "src/db/write_batch_test.cc",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- deps = [
- ":leveldb_testutil",
- ]
- }
-}
diff --git a/build/secondary/third_party/sfntly/BUILD.gn b/build/secondary/third_party/sfntly/BUILD.gn
deleted file mode 100644
index 111f1cd..0000000
--- a/build/secondary/third_party/sfntly/BUILD.gn
+++ /dev/null
@@ -1,131 +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.
-
-static_library("sfntly") {
- sources = [
- "cpp/src/sample/chromium/font_subsetter.cc",
- "cpp/src/sample/chromium/font_subsetter.h",
- "cpp/src/sample/chromium/subsetter_impl.cc",
- "cpp/src/sample/chromium/subsetter_impl.h",
- "cpp/src/sfntly/data/byte_array.cc",
- "cpp/src/sfntly/data/byte_array.h",
- "cpp/src/sfntly/data/font_data.cc",
- "cpp/src/sfntly/data/font_data.h",
- "cpp/src/sfntly/data/font_input_stream.cc",
- "cpp/src/sfntly/data/font_input_stream.h",
- "cpp/src/sfntly/data/font_output_stream.cc",
- "cpp/src/sfntly/data/font_output_stream.h",
- "cpp/src/sfntly/data/growable_memory_byte_array.cc",
- "cpp/src/sfntly/data/growable_memory_byte_array.h",
- "cpp/src/sfntly/data/memory_byte_array.cc",
- "cpp/src/sfntly/data/memory_byte_array.h",
- "cpp/src/sfntly/data/readable_font_data.cc",
- "cpp/src/sfntly/data/readable_font_data.h",
- "cpp/src/sfntly/data/writable_font_data.cc",
- "cpp/src/sfntly/data/writable_font_data.h",
- "cpp/src/sfntly/font.cc",
- "cpp/src/sfntly/font.h",
- "cpp/src/sfntly/font_factory.cc",
- "cpp/src/sfntly/font_factory.h",
- "cpp/src/sfntly/math/fixed1616.h",
- "cpp/src/sfntly/math/font_math.h",
- "cpp/src/sfntly/port/atomic.h",
- "cpp/src/sfntly/port/config.h",
- "cpp/src/sfntly/port/endian.h",
- "cpp/src/sfntly/port/exception_type.h",
- "cpp/src/sfntly/port/file_input_stream.cc",
- "cpp/src/sfntly/port/file_input_stream.h",
- "cpp/src/sfntly/port/input_stream.h",
- "cpp/src/sfntly/port/lock.cc",
- "cpp/src/sfntly/port/lock.h",
- "cpp/src/sfntly/port/memory_input_stream.cc",
- "cpp/src/sfntly/port/memory_input_stream.h",
- "cpp/src/sfntly/port/memory_output_stream.cc",
- "cpp/src/sfntly/port/memory_output_stream.h",
- "cpp/src/sfntly/port/output_stream.h",
- "cpp/src/sfntly/port/refcount.h",
- "cpp/src/sfntly/port/type.h",
- "cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc",
- "cpp/src/sfntly/table/bitmap/big_glyph_metrics.h",
- "cpp/src/sfntly/table/bitmap/bitmap_glyph.cc",
- "cpp/src/sfntly/table/bitmap/bitmap_glyph.h",
- "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc",
- "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h",
- "cpp/src/sfntly/table/bitmap/bitmap_size_table.cc",
- "cpp/src/sfntly/table/bitmap/bitmap_size_table.h",
- "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc",
- "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h",
- "cpp/src/sfntly/table/bitmap/ebdt_table.cc",
- "cpp/src/sfntly/table/bitmap/ebdt_table.h",
- "cpp/src/sfntly/table/bitmap/eblc_table.cc",
- "cpp/src/sfntly/table/bitmap/eblc_table.h",
- "cpp/src/sfntly/table/bitmap/ebsc_table.cc",
- "cpp/src/sfntly/table/bitmap/ebsc_table.h",
- "cpp/src/sfntly/table/bitmap/glyph_metrics.cc",
- "cpp/src/sfntly/table/bitmap/glyph_metrics.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format1.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format2.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format3.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format4.h",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc",
- "cpp/src/sfntly/table/bitmap/index_sub_table_format5.h",
- "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc",
- "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h",
- "cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc",
- "cpp/src/sfntly/table/bitmap/small_glyph_metrics.h",
- "cpp/src/sfntly/table/byte_array_table_builder.cc",
- "cpp/src/sfntly/table/byte_array_table_builder.h",
- "cpp/src/sfntly/table/core/cmap_table.cc",
- "cpp/src/sfntly/table/core/cmap_table.h",
- "cpp/src/sfntly/table/core/font_header_table.cc",
- "cpp/src/sfntly/table/core/font_header_table.h",
- "cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc",
- "cpp/src/sfntly/table/core/horizontal_device_metrics_table.h",
- "cpp/src/sfntly/table/core/horizontal_header_table.cc",
- "cpp/src/sfntly/table/core/horizontal_header_table.h",
- "cpp/src/sfntly/table/core/horizontal_metrics_table.cc",
- "cpp/src/sfntly/table/core/horizontal_metrics_table.h",
- "cpp/src/sfntly/table/core/maximum_profile_table.cc",
- "cpp/src/sfntly/table/core/maximum_profile_table.h",
- "cpp/src/sfntly/table/core/name_table.cc",
- "cpp/src/sfntly/table/core/name_table.h",
- "cpp/src/sfntly/table/core/os2_table.cc",
- "cpp/src/sfntly/table/core/os2_table.h",
- "cpp/src/sfntly/table/font_data_table.cc",
- "cpp/src/sfntly/table/font_data_table.h",
- "cpp/src/sfntly/table/generic_table_builder.cc",
- "cpp/src/sfntly/table/generic_table_builder.h",
- "cpp/src/sfntly/table/header.cc",
- "cpp/src/sfntly/table/header.h",
- "cpp/src/sfntly/table/subtable.cc",
- "cpp/src/sfntly/table/subtable.h",
- "cpp/src/sfntly/table/subtable_container_table.h",
- "cpp/src/sfntly/table/table.cc",
- "cpp/src/sfntly/table/table.h",
- "cpp/src/sfntly/table/table_based_table_builder.cc",
- "cpp/src/sfntly/table/table_based_table_builder.h",
- "cpp/src/sfntly/table/truetype/glyph_table.cc",
- "cpp/src/sfntly/table/truetype/glyph_table.h",
- "cpp/src/sfntly/table/truetype/loca_table.cc",
- "cpp/src/sfntly/table/truetype/loca_table.h",
- "cpp/src/sfntly/tag.cc",
- "cpp/src/sfntly/tag.h",
- ]
-
- defines = [ "SFNTLY_NO_EXCEPTION" ]
- include_dirs = [ "cpp/src" ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-
- deps = [
- "//third_party/icu:icuuc",
- ]
-}
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni
index 5d3b1e4..09a04c1 100644
--- a/build/secondary/tools/grit/grit_rule.gni
+++ b/build/secondary/tools/grit/grit_rule.gni
@@ -146,7 +146,7 @@
if (use_nss_certs) {
grit_defines += [
"-D",
- "use_nss",
+ "use_nss_certs",
]
}
@@ -204,6 +204,12 @@
"enable_extensions",
]
}
+if (enable_media_router) {
+ grit_defines += [
+ "-D",
+ "enable_media_router",
+ ]
+}
if (enable_plugins) {
grit_defines += [
"-D",
@@ -299,11 +305,14 @@
assert(defined(invoker.source),
"\"source\" must be defined for the grit template $target_name")
+ grit_inputs = [ invoker.source ]
+
if (defined(invoker.resource_ids)) {
resource_ids = invoker.resource_ids
} else {
resource_ids = grit_resource_id_file
}
+ grit_inputs += [ resource_ids ] # Script depends on ID file.
if (defined(invoker.output_dir)) {
output_dir = invoker.output_dir
@@ -331,8 +340,6 @@
grit_flags = [] # These are optional so default to empty list.
}
- grit_inputs = [ invoker.source ]
-
assert_files_flags = []
# We want to make sure the declared outputs actually match what Grit is
@@ -371,20 +378,8 @@
script = "//tools/grit/grit.py"
inputs = grit_inputs
- # TODO(knn): Remove this once grit has rolled to recognize the flag.
- depend_on_stamp =
- defined(invoker.depend_on_stamp) && invoker.depend_on_stamp
- if (depend_on_stamp) {
- # Need this for migrating existing targets without clobbering.
- depfile = "$output_dir/${grit_output_name}_stamp.d"
- outputs = [
- "${depfile}.stamp",
- ]
- } else {
- depfile = "$output_dir/${grit_output_name}.d"
- outputs = []
- }
- outputs += grit_outputs
+ depfile = "$output_dir/${grit_output_name}_stamp.d"
+ outputs = [ "${depfile}.stamp" ] + grit_outputs
args = [
"-i",
@@ -398,18 +393,15 @@
]
}
args += [
- "-o",
- rebased_output_dir,
- "--depdir",
- ".",
- "--depfile",
- rebase_path(depfile, root_build_dir),
- "--write-only-new=1",
- ]
- if (depend_on_stamp) {
- args += [ "--depend-on-stamp" ]
- }
- args += grit_defines
+ "-o",
+ rebased_output_dir,
+ "--depdir",
+ ".",
+ "--depfile",
+ rebase_path(depfile, root_build_dir),
+ "--write-only-new=1",
+ "--depend-on-stamp",
+ ] + grit_defines
# Add extra defines with -D flags.
if (defined(invoker.defines)) {
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 5f49f68..0192faa 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -211,12 +211,6 @@
target_os = target_os
target_cpu = target_cpu
- # TODO(dpranke): These values are here for backwards compatibility and
- # should be deleted when all of the builders and configs have been
- # updated.
- cpu_arch = current_cpu
- os = current_os
-
if (defined(invoker.is_clang)) {
is_clang = invoker.is_clang
}
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 18ee8b8..a4b8651 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -195,9 +195,6 @@
toolchain_args() {
current_os = invoker.toolchain_os
-
- # TODO(dpranke): os is here for backwards compatibility.
- os = current_os
}
}
}
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index e9461a4..05406c3 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -101,7 +101,7 @@
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
- rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
+ rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
}
tool("rc") {
@@ -201,9 +201,6 @@
# passed to the build. They are ignored when this is the default toolchain.
toolchain_args() {
current_cpu = invoker.current_cpu
-
- # TODO(dpranke): cpu_arch is here for backwards compatibility.
- cpu_arch = current_cpu
}
}
}
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
index d1c33e8..1a7f519 100755
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -115,6 +115,7 @@
for line in reversed(output.splitlines()):
if line.startswith('Cr-Commit-Position:'):
pos = line.rsplit()[-1].strip()
+ break
if not pos:
return VersionInfo('git', hsh)
return VersionInfo('git', '%s-%s' % (hsh, pos))
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 79919df..b7bd765 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -126,7 +126,7 @@
libs = []
if (is_android) {
- deps += [ "//testing/android:native_test_native_code" ]
+ deps += [ "//testing/android/native_test:native_test_native_code" ]
libs += [ "android" ]
}
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index af23813..a4fcc70 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4419,7 +4419,7 @@
# Make this behavior consistent within Chromium, and avoid leaking GL
# errors by generating the error in the command buffer instead of
# letting the GL driver generate it.
- code.append("base::IsNaN(%s)" % args[ndx].name)
+ code.append("std::isnan(%s)" % args[ndx].name)
if len(code):
file.Write(" if (%s) {\n" % " ||\n ".join(code))
file.Write(
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
index f0faded..e7a3a6c 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
@@ -90,7 +90,7 @@
TransferThread() : base::Thread(kAsyncTransferThreadName) {
Start();
#if defined(OS_ANDROID) || defined(OS_LINUX)
- SetPriority(base::kThreadPriority_Background);
+ SetPriority(base::ThreadPriority::BACKGROUND);
#endif
}
~TransferThread() override { Stop(); }
@@ -466,14 +466,14 @@
void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() {
if (state_->TransferIsInProgress()) {
#if defined(OS_ANDROID) || defined(OS_LINUX)
- g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display);
+ g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND);
#endif
state_->WaitForTransferCompletion();
DCHECK(!state_->TransferIsInProgress());
#if defined(OS_ANDROID) || defined(OS_LINUX)
- g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background);
+ g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND);
#endif
}
}
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
index 16089f6..47cdf9e 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
@@ -47,7 +47,7 @@
initialized_(false) {
Start();
#if defined(OS_ANDROID) || defined(OS_LINUX)
- SetPriority(base::kThreadPriority_Background);
+ SetPriority(base::ThreadPriority::BACKGROUND);
#endif
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0886768..efa9dbc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -17,7 +17,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
-#include "base/float_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 9a27c2f..18b2808 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2215,7 +2215,7 @@
*static_cast<const gles2::cmds::LineWidth*>(cmd_data);
(void)c;
GLfloat width = static_cast<GLfloat>(c.width);
- if (width <= 0.0f || base::IsNaN(width)) {
+ if (width <= 0.0f || std::isnan(width)) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "LineWidth", "width out of range");
return error::kNoError;
}
diff --git a/mojo/common/task_tracker_unittest.cc b/mojo/common/task_tracker_unittest.cc
index d476554..77f7da8 100644
--- a/mojo/common/task_tracker_unittest.cc
+++ b/mojo/common/task_tracker_unittest.cc
@@ -34,7 +34,7 @@
tracked_objects::ThreadData::Snapshot(&snapshot);
// Nested one is ignored.
- EXPECT_EQ(1U, snapshot.tasks.size());
+ EXPECT_EQ(1U, snapshot.phased_process_data_snapshots[0].tasks.size());
}
TEST_F(TaskTrackerTest, Twice) {
@@ -46,7 +46,7 @@
tracked_objects::ProcessDataSnapshot snapshot;
tracked_objects::ThreadData::Snapshot(&snapshot);
- EXPECT_EQ(2U, snapshot.tasks.size());
+ EXPECT_EQ(2U, snapshot.phased_process_data_snapshots[0].tasks.size());
}
} // namespace test
diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn
index cf509aa..95fcc46 100644
--- a/mojo/dart/embedder/BUILD.gn
+++ b/mojo/dart/embedder/BUILD.gn
@@ -360,7 +360,7 @@
"--output_bin",
rebase_path(isolate_snapshot, root_build_dir),
"--target_os",
- os,
+ current_os,
"--url_mapping=dart:mojo.builtin,$builtin_path",
"--url_mapping=dart:mojo.internal,$internal_path",
"--url_mapping=dart:mojo.io,$io_path",
diff --git a/mojo/public/tools/BUILD.gn b/mojo/public/tools/BUILD.gn
index 8b47bb9..9850a17 100644
--- a/mojo/public/tools/BUILD.gn
+++ b/mojo/public/tools/BUILD.gn
@@ -38,7 +38,7 @@
]
} else {
if (is_android) {
- assert(cpu_arch == "arm",
+ assert(current_cpu == "arm",
"Only arm version prebuilt netowrk_service.mojo is available.")
sources = [
"prebuilt/network_service/android-arm/$filename",
@@ -66,7 +66,7 @@
} else {
if (is_android) {
assert(
- cpu_arch == "arm",
+ target_cpu == "arm",
"Only arm version prebuilt netowrk_service_apptests.mojo is available.")
sources = [
"prebuilt/network_service_apptests/android-arm/$filename",
diff --git a/mojo/tools/mopy/gn.py b/mojo/tools/mopy/gn.py
index f171281..1e519da 100644
--- a/mojo/tools/mopy/gn.py
+++ b/mojo/tools/mopy/gn.py
@@ -65,9 +65,9 @@
gn_args["go_build_tool"] = config.values.get("go_build_tool")
if config.target_os == Config.OS_ANDROID:
- gn_args["os"] = "android"
+ gn_args["target_os"] = "android"
elif config.target_os == Config.OS_CHROMEOS:
- gn_args["os"] = "chromeos"
+ gn_args["target_os"] = "chromeos"
gn_args["use_glib"] = False
gn_args["use_system_harfbuzz"] = False
elif config.target_os == Config.OS_LINUX:
@@ -114,7 +114,7 @@
config_args["mojo_use_go"] = args.get("mojo_use_go", False)
if config_args["mojo_use_go"]:
config_args["go_build_tool"] = args.get("go_build_tool")
- config_args["target_os"] = args.get("os")
+ config_args["target_os"] = args.get("target_os")
config_args["target_cpu"] = args.get("target_cpu")
config_args["dcheck_always_on"] = args.get("dcheck_always_on")
return Config(**config_args)
diff --git a/mojo/tools/mopy/gn_unittest.py b/mojo/tools/mopy/gn_unittest.py
index 1aaaa6c..0e8768a 100644
--- a/mojo/tools/mopy/gn_unittest.py
+++ b/mojo/tools/mopy/gn_unittest.py
@@ -37,7 +37,7 @@
def testGNToConfigToGN(self):
"""Tests that gn to config to gn is the identity"""
configs_to_test = {
- "os": [None, "android", "chromeos"],
+ "target_os": [None, "android", "chromeos"],
"target_cpu": ["x86", "x64", "arm"],
"is_debug": [False, True],
"is_clang": [False, True],
@@ -49,10 +49,10 @@
}
for args in _iterate_over_config(configs_to_test):
- if args.get('os', None) == "chromeos":
- args['use_glib'] = False
- args['use_system_harfbuzz'] = False
- if args.get('os', None) is None and sys.platform[:5] == 'linux':
+ if args.get("target_os", None) == "chromeos":
+ args["use_glib"] = False
+ args["use_system_harfbuzz"] = False
+ if args.get("target_os", None) is None and sys.platform[:5] == "linux":
args["use_aura"] = False
args["use_glib"] = False
args["use_system_harfbuzz"] = False
diff --git a/mojo/tools/roll/build_v8.patch b/mojo/tools/roll/build_v8.patch
index 7de0f0a..5575f24 100644
--- a/mojo/tools/roll/build_v8.patch
+++ b/mojo/tools/roll/build_v8.patch
@@ -1,13 +1,12 @@
diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni
-index df6a4a3..05b673b 100644
+index db4ee4e..05b673b 100644
--- a/build/module_args/v8.gni
+++ b/build/module_args/v8.gni
-@@ -9,5 +9,7 @@ if (is_android) {
+@@ -9,4 +9,7 @@ if (is_android) {
# TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
enable_correct_v8_arch = false
--v8_use_external_startup_data =
-- !((is_android && is_android_webview_build) || is_chromeos || is_win)
+-v8_use_external_startup_data = !(is_chromeos || is_win)
+# Many V8 users in mojo do not support external startup data for V8, so
+# we disable it. If enabled, special care should be taken to ensure the
+# appropriate startup data is correctly bundled for apps.
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 211c22b..8496685 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -117,6 +117,7 @@
"seccomp-bpf/errorcode_unittest.cc",
"seccomp-bpf/sandbox_bpf_unittest.cc",
"seccomp-bpf/syscall_unittest.cc",
+ "seccomp-bpf/trap_unittest.cc",
]
}
if (compile_credentials) {
@@ -147,7 +148,7 @@
":sandbox_linux_unittests_sources",
]
if (is_android) {
- deps += [ "//testing/android:native_test_native_code" ]
+ deps += [ "//testing/android/native_test:native_test_native_code" ]
}
}
@@ -288,15 +289,16 @@
source_set("sandbox_services_headers") {
sources = [
- "system_headers/android_arm64_ucontext.h",
- "system_headers/android_arm_ucontext.h",
- "system_headers/android_futex.h",
- "system_headers/android_i386_ucontext.h",
- "system_headers/android_ucontext.h",
"system_headers/arm64_linux_syscalls.h",
+ "system_headers/arm64_linux_ucontext.h",
"system_headers/arm_linux_syscalls.h",
+ "system_headers/arm_linux_ucontext.h",
+ "system_headers/i386_linux_ucontext.h",
+ "system_headers/linux_futex.h",
"system_headers/linux_seccomp.h",
+ "system_headers/linux_signal.h",
"system_headers/linux_syscalls.h",
+ "system_headers/linux_ucontext.h",
"system_headers/x86_32_linux_syscalls.h",
"system_headers/x86_64_linux_syscalls.h",
]
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.h b/sandbox/linux/bpf_dsl/bpf_dsl.h
index 63b095d..365e9b5 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl.h
+++ b/sandbox/linux/bpf_dsl/bpf_dsl.h
@@ -33,8 +33,8 @@
// class SillyPolicy : public Policy {
// public:
// SillyPolicy() {}
-// virtual ~SillyPolicy() {}
-// virtual ResultExpr EvaluateSyscall(int sysno) const override {
+// ~SillyPolicy() override {}
+// ResultExpr EvaluateSyscall(int sysno) const override {
// if (sysno == __NR_fcntl) {
// Arg<int> fd(0), cmd(1);
// Arg<unsigned long> flags(2);
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
index dba421f..398ec59 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
@@ -26,6 +26,7 @@
#include "sandbox/linux/bpf_dsl/trap_registry.h"
#include "sandbox/linux/bpf_dsl/verifier.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
#define CASES SANDBOX_BPF_DSL_CASES
diff --git a/sandbox/linux/bpf_dsl/codegen.cc b/sandbox/linux/bpf_dsl/codegen.cc
index 793d95d..99b78ed 100644
--- a/sandbox/linux/bpf_dsl/codegen.cc
+++ b/sandbox/linux/bpf_dsl/codegen.cc
@@ -4,12 +4,11 @@
#include "sandbox/linux/bpf_dsl/codegen.h"
-#include <linux/filter.h>
-
#include <limits>
#include <utility>
#include "base/logging.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
// This CodeGen implementation strives for simplicity while still
// generating acceptable BPF programs under typical usage patterns
diff --git a/sandbox/linux/bpf_dsl/codegen_unittest.cc b/sandbox/linux/bpf_dsl/codegen_unittest.cc
index 3abfc85..5961822 100644
--- a/sandbox/linux/bpf_dsl/codegen_unittest.cc
+++ b/sandbox/linux/bpf_dsl/codegen_unittest.cc
@@ -4,8 +4,6 @@
#include "sandbox/linux/bpf_dsl/codegen.h"
-#include <linux/filter.h>
-
#include <map>
#include <utility>
#include <vector>
@@ -13,6 +11,7 @@
#include "base/macros.h"
#include "base/md5.h"
#include "base/strings/string_piece.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
@@ -63,7 +62,7 @@
}
std::string Base16() const {
- return MD5DigestToBase16(digest_);
+ return base::MD5DigestToBase16(digest_);
}
base::MD5Digest digest_;
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc
index 82c9852..d0c8f75 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.cc
+++ b/sandbox/linux/bpf_dsl/dump_bpf.cc
@@ -8,6 +8,7 @@
#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/bpf_dsl/trap_registry.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
@@ -79,19 +80,22 @@
}
break;
case BPF_ALU:
- fprintf(stderr, BPF_OP(iter->code) == BPF_NEG
- ? "A := -A\n" : "A := A %s 0x%x\n",
- BPF_OP(iter->code) == BPF_ADD ? "+" :
- BPF_OP(iter->code) == BPF_SUB ? "-" :
- BPF_OP(iter->code) == BPF_MUL ? "*" :
- BPF_OP(iter->code) == BPF_DIV ? "/" :
- BPF_OP(iter->code) == BPF_MOD ? "%" :
- BPF_OP(iter->code) == BPF_OR ? "|" :
- BPF_OP(iter->code) == BPF_XOR ? "^" :
- BPF_OP(iter->code) == BPF_AND ? "&" :
- BPF_OP(iter->code) == BPF_LSH ? "<<" :
- BPF_OP(iter->code) == BPF_RSH ? ">>" : "???",
- (int)iter->k);
+ if (BPF_OP(iter->code) == BPF_NEG) {
+ fprintf(stderr, "A := -A\n");
+ } else {
+ fprintf(stderr, "A := A %s 0x%x\n",
+ BPF_OP(iter->code) == BPF_ADD ? "+" :
+ BPF_OP(iter->code) == BPF_SUB ? "-" :
+ BPF_OP(iter->code) == BPF_MUL ? "*" :
+ BPF_OP(iter->code) == BPF_DIV ? "/" :
+ BPF_OP(iter->code) == BPF_MOD ? "%" :
+ BPF_OP(iter->code) == BPF_OR ? "|" :
+ BPF_OP(iter->code) == BPF_XOR ? "^" :
+ BPF_OP(iter->code) == BPF_AND ? "&" :
+ BPF_OP(iter->code) == BPF_LSH ? "<<" :
+ BPF_OP(iter->code) == BPF_RSH ? ">>" : "???",
+ (int)iter->k);
+ }
break;
default:
fprintf(stderr, "???\n");
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
index a26a166..a747770 100644
--- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -5,8 +5,6 @@
#ifndef SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
#define SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
-#include <asm/unistd.h> // For __NR_SYSCALL_BASE
-
#if defined(__x86_64__)
#define MIN_SYSCALL 0u
@@ -25,15 +23,19 @@
// and a "ghost syscall private to the kernel", cmpxchg,
// at |__ARM_NR_BASE+0x00fff0|.
// See </arch/arm/include/asm/unistd.h> in the Linux kernel.
-#define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE)
+
+// __NR_SYSCALL_BASE is 0 in thumb and ARM EABI.
+#define MIN_SYSCALL 0u
#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u)
-#define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE)
+// __ARM_NR_BASE is __NR_SYSCALL_BASE + 0xf0000u
+#define MIN_PRIVATE_SYSCALL 0xf0000u
#define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u)
-#define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u)
+#define MIN_GHOST_SYSCALL (MIN_PRIVATE_SYSCALL + 0xfff0u)
#define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u)
#elif defined(__mips__) && (_MIPS_SIM == _ABIO32)
+#include <asm/unistd.h> // for __NR_O32_Linux and __NR_Linux_syscalls
#define MIN_SYSCALL __NR_O32_Linux
#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls)
#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index f508b30..d4d5280 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -5,7 +5,6 @@
#include "sandbox/linux/bpf_dsl/policy_compiler.h"
#include <errno.h>
-#include <linux/filter.h>
#include <sys/syscall.h>
#include <limits>
@@ -21,6 +20,7 @@
#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "sandbox/linux/bpf_dsl/verifier.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
index 7fd0e67..7f4866d 100644
--- a/sandbox/linux/bpf_dsl/seccomp_macros.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -5,9 +5,6 @@
#ifndef SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
#define SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
-#include <asm/unistd.h>
-#include <linux/filter.h>
-
#include <sys/cdefs.h>
// Old Bionic versions do not have sys/user.h. The if can be removed once we no
// longer need to support these old Bionic versions.
diff --git a/sandbox/linux/bpf_dsl/verifier.cc b/sandbox/linux/bpf_dsl/verifier.cc
index adbc960..417c663 100644
--- a/sandbox/linux/bpf_dsl/verifier.cc
+++ b/sandbox/linux/bpf_dsl/verifier.cc
@@ -15,6 +15,7 @@
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 4305b41..7724223 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -278,18 +278,18 @@
{ 'target_name': 'sandbox_services_headers',
'type': 'none',
'sources': [
- 'system_headers/android_arm64_ucontext.h',
- 'system_headers/android_arm_ucontext.h',
- 'system_headers/android_futex.h',
- 'system_headers/android_i386_ucontext.h',
- 'system_headers/android_mips_ucontext.h',
- 'system_headers/android_ucontext.h',
'system_headers/arm64_linux_syscalls.h',
+ 'system_headers/arm64_linux_ucontext.h',
'system_headers/arm_linux_syscalls.h',
+ 'system_headers/arm_linux_ucontext.h',
'system_headers/capability.h',
+ 'system_headers/i386_linux_ucontext.h',
+ 'system_headers/linux_futex.h',
'system_headers/linux_seccomp.h',
'system_headers/linux_syscalls.h',
+ 'system_headers/linux_ucontext.h',
'system_headers/mips_linux_syscalls.h',
+ 'system_headers/mips_linux_ucontext.h',
'system_headers/x86_32_linux_syscalls.h',
'system_headers/x86_64_linux_syscalls.h',
],
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index c558a0d..ce7817d 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -53,6 +53,7 @@
'seccomp-bpf/errorcode_unittest.cc',
'seccomp-bpf/sandbox_bpf_unittest.cc',
'seccomp-bpf/syscall_unittest.cc',
+ 'seccomp-bpf/trap_unittest.cc',
],
}],
[ 'compile_credentials==1', {
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index e6e8934..614849f 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -6,7 +6,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <linux/futex.h>
#include <sched.h>
#include <signal.h>
#include <string.h>
@@ -32,7 +31,7 @@
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
-#include "sandbox/linux/system_headers/android_futex.h"
+#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 21fd4d7..d449156 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -9,7 +9,6 @@
#include <sys/syscall.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
index 38e02bf..c64e994 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -5,7 +5,8 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_
#define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_
-#include "base/basictypes.h"
+#include <stdint.h>
+
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
#include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index c081b29..282e727 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -7,10 +7,10 @@
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
-#include <linux/futex.h>
#include <linux/net.h>
#include <sched.h>
#include <signal.h>
+#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
@@ -21,7 +21,6 @@
#include <time.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/time/time.h"
@@ -30,12 +29,11 @@
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#if defined(OS_ANDROID)
-#include "sandbox/linux/system_headers/android_futex.h"
-
#if !defined(F_DUPFD_CLOEXEC)
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
#endif
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
index 1dbd949..5ba6335 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
@@ -5,7 +5,7 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_
#define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "build/build_config.h"
#include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
index 1869913..7736c15 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
@@ -25,9 +25,9 @@
explicit BPFTesterCompatibilityDelegate(TestFunction test_function)
: aux_(), test_function_(test_function) {}
- virtual ~BPFTesterCompatibilityDelegate() {}
+ ~BPFTesterCompatibilityDelegate() override {}
- virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
+ scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
// The current method is guaranteed to only run in the child process
// running the test. In this process, the current object is guaranteed
// to live forever. So it's ok to pass aux_pointer_for_policy_ to
@@ -35,7 +35,7 @@
return scoped_ptr<bpf_dsl::Policy>(new Policy(&aux_));
}
- virtual void RunTestFunction() override {
+ void RunTestFunction() override {
// Run the actual test.
// The current object is guaranteed to live forever in the child process
// where this will run.
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h
index 57de1dd..cc4debd 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -102,12 +102,12 @@
public:
explicit BPFTesterSimpleDelegate(void (*test_function)(void))
: test_function_(test_function) {}
- virtual ~BPFTesterSimpleDelegate() {}
+ ~BPFTesterSimpleDelegate() override {}
- virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
+ scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
return scoped_ptr<bpf_dsl::Policy>(new PolicyClass());
}
- virtual void RunTestFunction() override {
+ void RunTestFunction() override {
DCHECK(test_function_);
test_function_();
}
diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc
index 777c9d1..3baf1f1 100644
--- a/sandbox/linux/seccomp-bpf/die.cc
+++ b/sandbox/linux/seccomp-bpf/die.cc
@@ -16,6 +16,8 @@
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
namespace sandbox {
@@ -32,7 +34,10 @@
// to a defined state; but we have not way to verify whether we actually
// succeeded in doing so. Nonetheless, triggering a fatal signal could help
// us terminate.
- signal(SIGSEGV, SIG_DFL);
+ struct sigaction sa = {};
+ sa.sa_handler = LINUX_SIG_DFL;
+ sa.sa_flags = LINUX_SA_RESTART;
+ sys_sigaction(LINUX_SIGSEGV, &sa, nullptr);
Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
if (*(volatile char*)0) {
}
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index c96642e..239043e 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -11,7 +11,6 @@
#endif
#include <errno.h>
-#include <linux/filter.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>
@@ -34,6 +33,7 @@
#include "sandbox/linux/services/proc_util.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
@@ -59,9 +59,40 @@
return false;
}
+// LG introduced a buggy syscall, sys_set_media_ext, with the same number as
+// seccomp. Return true if the current kernel has this buggy syscall.
+//
+// We want this to work with upcoming versions of seccomp, so we pass bogus
+// flags that are unlikely to ever be used by the kernel. A normal kernel would
+// return -EINVAL, but a buggy LG kernel would return 1.
+bool KernelHasLGBug() {
+#if defined(OS_ANDROID)
+ // sys_set_media will see this as NULL, which should be a safe (non-crashing)
+ // way to invoke it. A genuine seccomp syscall will see it as
+ // SECCOMP_SET_MODE_STRICT.
+ const unsigned int operation = 0;
+ // Chosen by fair dice roll. Guaranteed to be random.
+ const unsigned int flags = 0xf7a46a5c;
+ const int rv = sys_seccomp(operation, flags, nullptr);
+ // A genuine kernel would return -EINVAL (which would set rv to -1 and errno
+ // to EINVAL), or at the very least return some kind of error (which would
+ // set rv to -1). Any other behavior indicates that whatever code received
+ // our syscall was not the real seccomp.
+ if (rv != -1) {
+ return true;
+ }
+#endif // defined(OS_ANDROID)
+
+ return false;
+}
+
// Check if the kernel supports seccomp-filter via the seccomp system call
// and the TSYNC feature to enable seccomp on all threads.
bool KernelSupportsSeccompTsync() {
+ if (KernelHasLGBug()) {
+ return false;
+ }
+
errno = 0;
const int rv =
sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr);
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
index cb051d2..321ea9a 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
@@ -5,13 +5,13 @@
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h"
#include <fcntl.h>
-#include <linux/filter.h>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 9fce1da..3b3c8db 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -4,10 +4,9 @@
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include <asm/unistd.h>
#include <errno.h>
+#include <stdint.h>
-#include "base/basictypes.h"
#include "base/logging.h"
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index dfb44eb..ccfc88d 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -9,13 +9,9 @@
#include <stdint.h>
#include "base/macros.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/sandbox_export.h"
-// Android's signal.h doesn't define ucontext etc.
-#if defined(OS_ANDROID)
-#include "sandbox/linux/system_headers/android_ucontext.h"
-#endif
-
namespace sandbox {
// This purely static class can be used to perform system calls with some
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 6bd3288..5fdee6c 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -13,7 +13,6 @@
#include <vector>
-#include "base/basictypes.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 145e624..79b7569 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -17,12 +17,9 @@
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
-
-// Android's signal.h doesn't define ucontext etc.
-#if defined(OS_ANDROID)
-#include "sandbox/linux/system_headers/android_ucontext.h"
-#endif
+#include "sandbox/linux/system_headers/linux_signal.h"
namespace {
@@ -53,13 +50,13 @@
// possibly even worse.
bool GetIsInSigHandler(const ucontext_t* ctx) {
// Note: on Android, sigismember does not take a pointer to const.
- return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS);
+ return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS);
}
void SetIsInSigHandler() {
sigset_t mask;
- if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) ||
- sigprocmask(SIG_BLOCK, &mask, NULL)) {
+ if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) ||
+ sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) {
SANDBOX_DIE("Failed to block SIGBUS");
}
}
@@ -82,10 +79,13 @@
has_unsafe_traps_(false) {
// Set new SIGSYS handler
struct sigaction sa = {};
- sa.sa_sigaction = SigSysAction;
- sa.sa_flags = SA_SIGINFO | SA_NODEFER;
- struct sigaction old_sa;
- if (sigaction(SIGSYS, &sa, &old_sa) < 0) {
+ // In some toolchain, sa_sigaction is not declared in struct sigaction.
+ // So, here cast the pointer to the sa_handler's type. This works because
+ // |sa_handler| and |sa_sigaction| shares the same memory.
+ sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction);
+ sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER;
+ struct sigaction old_sa = {};
+ if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) {
SANDBOX_DIE("Failed to configure SIGSYS handler");
}
@@ -99,8 +99,8 @@
// Unmask SIGSYS
sigset_t mask;
- if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) ||
- sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
+ if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) ||
+ sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) {
SANDBOX_DIE("Failed to configure SIGSYS handler");
}
}
@@ -120,7 +120,7 @@
return global_trap_;
}
-void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) {
+void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) {
if (!global_trap_) {
RAW_SANDBOX_DIE(
"This can't happen. Found no global singleton instance "
@@ -129,7 +129,7 @@
global_trap_->SigSys(nr, info, void_context);
}
-void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
+void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) {
// Signal handlers should always preserve "errno". Otherwise, we could
// trigger really subtle bugs.
const int old_errno = errno;
@@ -137,7 +137,7 @@
// Various sanity checks to make sure we actually received a signal
// triggered by a BPF filter. If something else triggered SIGSYS
// (e.g. kill()), there is really nothing we can do with this signal.
- if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
+ if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
info->si_errno <= 0 ||
static_cast<size_t>(info->si_errno) > trap_array_size_) {
// ATI drivers seem to send SIGSYS, so this cannot be FATAL.
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h
index 4073bfe..bbddeb7 100644
--- a/sandbox/linux/seccomp-bpf/trap.h
+++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -5,13 +5,13 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
#define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
-#include <signal.h>
#include <stdint.h>
#include <map>
#include "base/macros.h"
#include "sandbox/linux/bpf_dsl/trap_registry.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
@@ -57,11 +57,11 @@
// break subsequent system calls that trigger a SIGSYS.
~Trap() = delete;
- static void SigSysAction(int nr, siginfo_t* info, void* void_context);
+ static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context);
// Make sure that SigSys is not inlined in order to get slightly better crash
// dumps.
- void SigSys(int nr, siginfo_t* info, void* void_context)
+ void SigSys(int nr, LinuxSigInfo* info, void* void_context)
__attribute__((noinline));
// We have a global singleton that handles all of our SIGSYS traps. This
// variable must never be deallocated after it has been set up initially, as
diff --git a/sandbox/linux/seccomp-bpf/trap_unittest.cc b/sandbox/linux/seccomp-bpf/trap_unittest.cc
new file mode 100644
index 0000000..3d95e34
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/trap_unittest.cc
@@ -0,0 +1,30 @@
+// 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/seccomp-bpf/trap.h"
+
+#include <signal.h>
+
+#include "sandbox/linux/tests/unit_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+namespace {
+
+#if !defined(THREAD_SANITIZER)
+SANDBOX_TEST_ALLOW_NOISE(Trap, SigSysAction) {
+ // This creates a global Trap instance, and registers the signal handler
+ // (Trap::SigSysAction).
+ Trap::Registry();
+
+ // Send SIGSYS to self. If signal handler (SigSysAction) is not registered,
+ // the process will be terminated with status code -SIGSYS.
+ // Note that, SigSysAction handler would output an error message
+ // "Unexpected SIGSYS received." so it is necessary to allow the noise.
+ raise(SIGSYS);
+}
+#endif
+
+} // namespace
+} // namespace sandbox
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 2e66d97..35bb4dc 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -6,13 +6,13 @@
#include <errno.h>
#include <signal.h>
+#include <stdint.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -27,6 +27,7 @@
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/system_headers/capability.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
namespace sandbox {
@@ -40,8 +41,8 @@
bool GetRESIds(uid_t* resuid, gid_t* resgid) {
uid_t ruid, euid, suid;
gid_t rgid, egid, sgid;
- PCHECK(getresuid(&ruid, &euid, &suid) == 0);
- PCHECK(getresgid(&rgid, &egid, &sgid) == 0);
+ PCHECK(sys_getresuid(&ruid, &euid, &suid) == 0);
+ PCHECK(sys_getresgid(&rgid, &egid, &sgid) == 0);
const bool uids_are_equal = (ruid == euid) && (ruid == suid);
const bool gids_are_equal = (rgid == egid) && (rgid == sgid);
if (!uids_are_equal || !gids_are_equal) return false;
@@ -53,7 +54,7 @@
const int kExitSuccess = 0;
int ChrootToSelfFdinfo(void*) {
- RAW_CHECK(chroot("/proc/self/fdinfo/") == 0);
+ RAW_CHECK(sys_chroot("/proc/self/fdinfo/") == 0);
// CWD is essentially an implicit file descriptor, so be careful to not
// leave it behind.
@@ -89,9 +90,10 @@
#else
#error "Unsupported architecture"
#endif
+
pid = clone(ChrootToSelfFdinfo, stack,
- CLONE_VM | CLONE_VFORK | CLONE_FS | SIGCHLD, nullptr, nullptr,
- nullptr, nullptr);
+ CLONE_VM | CLONE_VFORK | CLONE_FS | LINUX_SIGCHLD, nullptr,
+ nullptr, nullptr, nullptr);
PCHECK(pid != -1);
int status = -1;
@@ -110,23 +112,24 @@
error == ENOSYS);
}
-// Converts a LinuxCapability to the corresponding Linux CAP_XXX value.
-int LinuxCapabilityToKernelValue(LinuxCapability cap) {
+// Converts a Capability to the corresponding Linux CAP_XXX value.
+int CapabilityToKernelValue(Credentials::Capability cap) {
switch (cap) {
- case LinuxCapability::kCapSysChroot:
+ case Credentials::Capability::SYS_CHROOT:
return CAP_SYS_CHROOT;
- case LinuxCapability::kCapSysAdmin:
+ case Credentials::Capability::SYS_ADMIN:
return CAP_SYS_ADMIN;
}
- LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap);
+ LOG(FATAL) << "Invalid Capability: " << static_cast<int>(cap);
return 0;
}
} // namespace.
+// static
bool Credentials::DropAllCapabilities(int proc_fd) {
- if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) {
+ if (!SetCapabilities(proc_fd, std::vector<Capability>())) {
return false;
}
@@ -134,14 +137,40 @@
return true;
}
+// static
bool Credentials::DropAllCapabilities() {
base::ScopedFD proc_fd(ProcUtil::OpenProc());
return Credentials::DropAllCapabilities(proc_fd.get());
}
// static
+bool Credentials::DropAllCapabilitiesOnCurrentThread() {
+ return SetCapabilitiesOnCurrentThread(std::vector<Capability>());
+}
+
+// static
+bool Credentials::SetCapabilitiesOnCurrentThread(
+ const std::vector<Capability>& caps) {
+ struct cap_hdr hdr = {};
+ hdr.version = _LINUX_CAPABILITY_VERSION_3;
+ struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
+
+ // Initially, cap has no capability flags set. Enable the effective and
+ // permitted flags only for the requested capabilities.
+ for (const Capability cap : caps) {
+ const int cap_num = CapabilityToKernelValue(cap);
+ const size_t index = CAP_TO_INDEX(cap_num);
+ const uint32_t mask = CAP_TO_MASK(cap_num);
+ data[index].effective |= mask;
+ data[index].permitted |= mask;
+ }
+
+ return sys_capset(&hdr, data) == 0;
+}
+
+// static
bool Credentials::SetCapabilities(int proc_fd,
- const std::vector<LinuxCapability>& caps) {
+ const std::vector<Capability>& caps) {
DCHECK_LE(0, proc_fd);
#if !defined(THREAD_SANITIZER)
@@ -150,21 +179,7 @@
CHECK(ThreadHelpers::IsSingleThreaded(proc_fd));
#endif
- struct cap_hdr hdr = {};
- hdr.version = _LINUX_CAPABILITY_VERSION_3;
- struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
-
- // Initially, cap has no capability flags set. Enable the effective and
- // permitted flags only for the requested capabilities.
- for (const LinuxCapability cap : caps) {
- const int cap_num = LinuxCapabilityToKernelValue(cap);
- const size_t index = CAP_TO_INDEX(cap_num);
- const uint32_t mask = CAP_TO_MASK(cap_num);
- data[index].effective |= mask;
- data[index].permitted |= mask;
- }
-
- return sys_capset(&hdr, data) == 0;
+ return SetCapabilitiesOnCurrentThread(caps);
}
bool Credentials::HasAnyCapability() {
@@ -183,14 +198,14 @@
return false;
}
-bool Credentials::HasCapability(LinuxCapability cap) {
+bool Credentials::HasCapability(Capability cap) {
struct cap_hdr hdr = {};
hdr.version = _LINUX_CAPABILITY_VERSION_3;
struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
PCHECK(sys_capget(&hdr, data) == 0);
- const int cap_num = LinuxCapabilityToKernelValue(cap);
+ const int cap_num = CapabilityToKernelValue(cap);
const size_t index = CAP_TO_INDEX(cap_num);
const uint32_t mask = CAP_TO_MASK(cap_num);
@@ -247,7 +262,7 @@
DVLOG(1) << "uids or gids differ!";
return false;
}
- int ret = unshare(CLONE_NEWUSER);
+ int ret = sys_unshare(CLONE_NEWUSER);
if (ret) {
const int unshare_errno = errno;
VLOG(1) << "Looks like unprivileged CLONE_NEWUSER may not be available "
diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h
index 83f2c70..0001dc7 100644
--- a/sandbox/linux/services/credentials.h
+++ b/sandbox/linux/services/credentials.h
@@ -14,26 +14,26 @@
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "sandbox/linux/system_headers/capability.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
-// For brevity, we only expose enums for the subset of capabilities we use.
-// This can be expanded as the need arises.
-enum class LinuxCapability {
- kCapSysChroot,
- kCapSysAdmin,
-};
-
// This class should be used to manipulate the current process' credentials.
// It is currently a stub used to manipulate POSIX.1e capabilities as
// implemented by the Linux kernel.
class SANDBOX_EXPORT Credentials {
public:
+ // For brevity, we only expose enums for the subset of capabilities we use.
+ // This can be expanded as the need arises.
+ enum class Capability {
+ SYS_CHROOT,
+ SYS_ADMIN,
+ };
+
// Drop all capabilities in the effective, inheritable and permitted sets for
// the current thread. For security reasons, since capabilities are
// per-thread, the caller is responsible for ensuring it is single-threaded
@@ -46,12 +46,20 @@
// Sets the effective and permitted capability sets for the current thread to
// the list of capabiltiies in |caps|. All other capability flags are cleared.
static bool SetCapabilities(int proc_fd,
- const std::vector<LinuxCapability>& caps)
+ const std::vector<Capability>& caps)
WARN_UNUSED_RESULT;
+ // Versions of the above functions which do not check that the process is
+ // single-threaded. After calling these functions, capabilities of other
+ // threads will not be changed. This is dangerous, do not use unless you nkow
+ // what you are doing.
+ static bool DropAllCapabilitiesOnCurrentThread() WARN_UNUSED_RESULT;
+ static bool SetCapabilitiesOnCurrentThread(
+ const std::vector<Capability>& caps) WARN_UNUSED_RESULT;
+
// Returns true if the current thread has either the effective, permitted, or
// inheritable flag set for the given capability.
- static bool HasCapability(LinuxCapability cap);
+ static bool HasCapability(Capability cap);
// Return true iff there is any capability in any of the capabilities sets
// of the current thread.
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index db19f6f..6b93c86 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -177,16 +177,17 @@
base::ScopedFD proc_fd(ProcUtil::OpenProc());
- CHECK(Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
- CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+ CHECK(Credentials::HasCapability(Credentials::Capability::SYS_ADMIN));
+ CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
- const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+ std::vector<Credentials::Capability> caps;
+ caps.push_back(Credentials::Capability::SYS_CHROOT);
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
- CHECK(!Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
- CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+ CHECK(!Credentials::HasCapability(Credentials::Capability::SYS_ADMIN));
+ CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
- const std::vector<LinuxCapability> no_caps;
+ const std::vector<Credentials::Capability> no_caps;
CHECK(Credentials::SetCapabilities(proc_fd.get(), no_caps));
CHECK(!Credentials::HasAnyCapability());
}
@@ -198,10 +199,11 @@
base::ScopedFD proc_fd(ProcUtil::OpenProc());
- CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+ CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
PCHECK(chroot("/") == 0);
- const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+ std::vector<Credentials::Capability> caps;
+ caps.push_back(Credentials::Capability::SYS_CHROOT);
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
PCHECK(chroot("/") == 0);
@@ -216,7 +218,8 @@
base::ScopedFD proc_fd(ProcUtil::OpenProc());
- const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+ std::vector<Credentials::Capability> caps;
+ caps.push_back(Credentials::Capability::SYS_CHROOT);
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
ScopedCap actual_cap(cap_get_proc());
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index 0f371eb..2379644 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -5,6 +5,7 @@
#include "sandbox/linux/services/namespace_sandbox.h"
#include <sched.h>
+#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
@@ -17,15 +18,22 @@
#include "base/environment.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/launch.h"
#include "base/process/process.h"
+#include "sandbox/linux/services/credentials.h"
#include "sandbox/linux/services/namespace_utils.h"
namespace sandbox {
namespace {
+const char kSandboxUSERNSEnvironmentVarName[] = "SBX_USER_NS";
+const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS";
+const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS";
+
+#if !defined(OS_NACL_NONSFI)
class WriteUidGidMapDelegate : public base::LaunchOptions::PreExecDelegate {
public:
WriteUidGidMapDelegate()
@@ -58,12 +66,24 @@
(*environ)[env_var] = value ? "1" : "";
}
-const char kSandboxUSERNSEnvironmentVarName[] = "SBX_USER_NS";
-const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS";
-const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS";
+// Linux supports up to 64 signals. This should be updated if that ever changes.
+int g_signal_exit_codes[64];
+
+void TerminationSignalHandler(int sig) {
+ // Return a special exit code so that the process is detected as terminated by
+ // a signal.
+ const size_t sig_idx = static_cast<size_t>(sig);
+ if (sig_idx < arraysize(g_signal_exit_codes)) {
+ _exit(g_signal_exit_codes[sig_idx]);
+ }
+
+ _exit(NamespaceSandbox::kDefaultExitCode);
+}
+#endif // !defined(OS_NACL_NONSFI)
} // namespace
+#if !defined(OS_NACL_NONSFI)
// static
base::Process NamespaceSandbox::LaunchProcess(
const base::CommandLine& cmdline,
@@ -111,6 +131,66 @@
}
// static
+pid_t NamespaceSandbox::ForkInNewPidNamespace(bool drop_capabilities_in_child) {
+ const pid_t pid =
+ base::ForkWithFlags(CLONE_NEWPID | SIGCHLD, nullptr, nullptr);
+ if (pid < 0) {
+ return pid;
+ }
+
+ if (pid == 0) {
+ DCHECK_EQ(1, getpid());
+ if (drop_capabilities_in_child) {
+ // Since we just forked, we are single-threaded, so this should be safe.
+ CHECK(Credentials::DropAllCapabilitiesOnCurrentThread());
+ }
+ return 0;
+ }
+
+ return pid;
+}
+
+// static
+void NamespaceSandbox::InstallDefaultTerminationSignalHandlers() {
+ static const int kDefaultTermSignals[] = {
+ SIGHUP, SIGINT, SIGABRT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2,
+ };
+
+ for (const int sig : kDefaultTermSignals) {
+ InstallTerminationSignalHandler(sig, kDefaultExitCode);
+ }
+}
+
+// static
+bool NamespaceSandbox::InstallTerminationSignalHandler(
+ int sig,
+ int exit_code) {
+ struct sigaction old_action;
+ PCHECK(sigaction(sig, nullptr, &old_action) == 0);
+
+ if (old_action.sa_flags & SA_SIGINFO &&
+ old_action.sa_sigaction != nullptr) {
+ return false;
+ } else if (old_action.sa_handler != SIG_DFL) {
+ return false;
+ }
+
+ const size_t sig_idx = static_cast<size_t>(sig);
+ CHECK_LT(sig_idx, arraysize(g_signal_exit_codes));
+
+ DCHECK_GE(exit_code, 0);
+ DCHECK_LT(exit_code, 256);
+
+ g_signal_exit_codes[sig_idx] = exit_code;
+
+ struct sigaction action = {};
+ action.sa_handler = &TerminationSignalHandler;
+ PCHECK(sigaction(sig, &action, nullptr) == 0);
+ return true;
+}
+#endif // !defined(OS_NACL_NONSFI)
+
+// static
bool NamespaceSandbox::InNewUserNamespace() {
return getenv(kSandboxUSERNSEnvironmentVarName) != nullptr;
}
diff --git a/sandbox/linux/services/namespace_sandbox.h b/sandbox/linux/services/namespace_sandbox.h
index b92f581..80097fb 100644
--- a/sandbox/linux/services/namespace_sandbox.h
+++ b/sandbox/linux/services/namespace_sandbox.h
@@ -5,6 +5,8 @@
#ifndef SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
#define SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
+#include <sys/types.h>
+
#include <string>
#include <vector>
@@ -35,6 +37,9 @@
// Credentials::DropAllCapabilities().
class SANDBOX_EXPORT NamespaceSandbox {
public:
+#if !defined(OS_NACL_NONSFI)
+ static const int kDefaultExitCode = 1;
+
// Launch a new process inside its own user/PID/network namespaces (depending
// on kernel support). Requires at a minimum that user namespaces are
// supported (use Credentials::CanCreateProcessInNewUserNS to check this).
@@ -47,6 +52,39 @@
static base::Process LaunchProcess(const std::vector<std::string>& argv,
const base::LaunchOptions& options);
+ // Forks a process in its own PID namespace. The child process is the init
+ // process inside of the PID namespace, so if the child needs to fork further,
+ // it should call CreateInitProcessReaper, which turns the init process into a
+ // reaper process.
+ //
+ // Otherwise, the child should setup handlers for signals which should
+ // terminate the process using InstallDefaultTerminationSignalHandlers or
+ // InstallTerminationSignalHandler. This works around the fact that init
+ // processes ignore such signals unless they have an explicit handler set.
+ //
+ // This function requries CAP_SYS_ADMIN. If |drop_capabilities_in_child| is
+ // true, then capabilities are dropped in the child.
+ static pid_t ForkInNewPidNamespace(bool drop_capabilities_in_child);
+
+ // Installs a signal handler for:
+ //
+ // SIGHUP, SIGINT, SIGABRT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
+ //
+ // that exits with kDefaultExitCode. These are signals whose default action is
+ // to terminate the program (apart from SIGILL, SIGFPE, and SIGSEGV, which
+ // will still terminate the process if e.g. an illegal instruction is
+ // encountered, etc.).
+ //
+ // If any of these already had a signal handler installed, this function will
+ // not override them.
+ static void InstallDefaultTerminationSignalHandlers();
+
+ // Installs a signal handler for |sig| which exits with |exit_code|. If a
+ // signal handler was already present for |sig|, does nothing and returns
+ // false.
+ static bool InstallTerminationSignalHandler(int sig, int exit_code);
+#endif // !defined(OS_NACL_NONSFI)
+
// Returns whether the namespace sandbox created a new user, PID, and network
// namespace. In particular, InNewUserNamespace should return true iff the
// process was started via this class.
diff --git a/sandbox/linux/services/namespace_sandbox_unittest.cc b/sandbox/linux/services/namespace_sandbox_unittest.cc
index 8bb0bff..547ef67 100644
--- a/sandbox/linux/services/namespace_sandbox_unittest.cc
+++ b/sandbox/linux/services/namespace_sandbox_unittest.cc
@@ -4,6 +4,7 @@
#include "sandbox/linux/services/namespace_sandbox.h"
+#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -118,6 +119,99 @@
TestProc("NestedNamespaceSandbox");
}
+const int kNormalExitCode = 0;
+const int kSignalTerminationExitCode = 255;
+
+// Ensure that CHECK(false) is distinguishable from _exit(kNormalExitCode).
+// Allowing noise since CHECK(false) will write a stack trace to stderr.
+SANDBOX_TEST_ALLOW_NOISE(ForkInNewPidNamespace, CheckDoesNotReturnZero) {
+ if (!Credentials::CanCreateProcessInNewUserNS()) {
+ return;
+ }
+
+ CHECK(sandbox::Credentials::MoveToNewUserNS());
+ const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+ /*drop_capabilities_in_child=*/true);
+ CHECK_GE(pid, 0);
+
+ if (pid == 0) {
+ CHECK(false);
+ _exit(kNormalExitCode);
+ }
+
+ int status;
+ PCHECK(waitpid(pid, &status, 0) == pid);
+ if (WIFEXITED(status)) {
+ CHECK_NE(kNormalExitCode, WEXITSTATUS(status));
+ }
+}
+
+SANDBOX_TEST(ForkInNewPidNamespace, BasicUsage) {
+ if (!Credentials::CanCreateProcessInNewUserNS()) {
+ return;
+ }
+
+ CHECK(sandbox::Credentials::MoveToNewUserNS());
+ const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+ /*drop_capabilities_in_child=*/true);
+ CHECK_GE(pid, 0);
+
+ if (pid == 0) {
+ CHECK_EQ(1, getpid());
+ CHECK(!Credentials::HasAnyCapability());
+ _exit(kNormalExitCode);
+ }
+
+ int status;
+ PCHECK(waitpid(pid, &status, 0) == pid);
+ CHECK(WIFEXITED(status));
+ CHECK_EQ(kNormalExitCode, WEXITSTATUS(status));
+}
+
+SANDBOX_TEST(ForkInNewPidNamespace, ExitWithSignal) {
+ if (!Credentials::CanCreateProcessInNewUserNS()) {
+ return;
+ }
+
+ CHECK(sandbox::Credentials::MoveToNewUserNS());
+ const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+ /*drop_capabilities_in_child=*/true);
+ CHECK_GE(pid, 0);
+
+ if (pid == 0) {
+ CHECK_EQ(1, getpid());
+ CHECK(!Credentials::HasAnyCapability());
+ CHECK(NamespaceSandbox::InstallTerminationSignalHandler(
+ SIGTERM, kSignalTerminationExitCode));
+ while (true) {
+ raise(SIGTERM);
+ }
+ }
+
+ int status;
+ PCHECK(waitpid(pid, &status, 0) == pid);
+ CHECK(WIFEXITED(status));
+ CHECK_EQ(kSignalTerminationExitCode, WEXITSTATUS(status));
+}
+
+volatile sig_atomic_t signal_handler_called;
+void ExitSuccessfully(int sig) {
+ signal_handler_called = 1;
+}
+
+SANDBOX_TEST(InstallTerminationSignalHandler, DoesNotOverrideExistingHandlers) {
+ struct sigaction action = {};
+ action.sa_handler = &ExitSuccessfully;
+ PCHECK(sigaction(SIGUSR1, &action, nullptr) == 0);
+
+ NamespaceSandbox::InstallDefaultTerminationSignalHandlers();
+ CHECK(!NamespaceSandbox::InstallTerminationSignalHandler(
+ SIGUSR1, kSignalTerminationExitCode));
+
+ raise(SIGUSR1);
+ CHECK_EQ(1, signal_handler_called);
+}
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/services/resource_limits.h b/sandbox/linux/services/resource_limits.h
index 488a5c5..3464dab 100644
--- a/sandbox/linux/services/resource_limits.h
+++ b/sandbox/linux/services/resource_limits.h
@@ -7,7 +7,6 @@
#include <sys/resource.h>
-#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/services/scoped_process.cc b/sandbox/linux/services/scoped_process.cc
index 4433201..65af487 100644
--- a/sandbox/linux/services/scoped_process.cc
+++ b/sandbox/linux/services/scoped_process.cc
@@ -12,7 +12,6 @@
#include <sys/wait.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
diff --git a/sandbox/linux/services/scoped_process.h b/sandbox/linux/services/scoped_process.h
index a28131e..bddbd55 100644
--- a/sandbox/linux/services/scoped_process.h
+++ b/sandbox/linux/services/scoped_process.h
@@ -5,8 +5,8 @@
#ifndef SANDBOX_LINUX_SERVICES_SCOPED_PROCESS_H_
#define SANDBOX_LINUX_SERVICES_SCOPED_PROCESS_H_
-#include "base/basictypes.h"
#include "base/callback_forward.h"
+#include "base/macros.h"
#include "base/process/process_handle.h"
#include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/services/scoped_process_unittest.cc b/sandbox/linux/services/scoped_process_unittest.cc
index 82b85b9..8bd2847 100644
--- a/sandbox/linux/services/scoped_process_unittest.cc
+++ b/sandbox/linux/services/scoped_process_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "sandbox/linux/services/scoped_process.h"
+
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -9,7 +11,6 @@
#include <sys/wait.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
@@ -18,7 +19,6 @@
#include "base/posix/eintr_wrapper.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
-#include "sandbox/linux/services/scoped_process.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
index 5a4045b..fdfcb94 100644
--- a/sandbox/linux/services/syscall_wrappers.cc
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -12,11 +12,14 @@
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
+#include <cstring>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/third_party/valgrind/valgrind.h"
#include "build/build_config.h"
+#include "sandbox/linux/system_headers/capability.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
@@ -45,6 +48,8 @@
RAW_LOG(FATAL, "Invalid usage of sys_clone");
}
+ if (ptid) MSAN_UNPOISON(ptid, sizeof(*ptid));
+ if (ctid) MSAN_UNPOISON(ctid, sizeof(*ctid));
// See kernel/fork.c in Linux. There is different ordering of sys_clone
// parameters depending on CONFIG_CLONE_BACKWARDS* configuration options.
#if defined(ARCH_CPU_X86_64)
@@ -74,15 +79,154 @@
int resource,
const struct rlimit64* new_limit,
struct rlimit64* old_limit) {
- return syscall(__NR_prlimit64, pid, resource, new_limit, old_limit);
+ int res = syscall(__NR_prlimit64, pid, resource, new_limit, old_limit);
+ if (res == 0 && old_limit) MSAN_UNPOISON(old_limit, sizeof(*old_limit));
+ return res;
}
int sys_capget(cap_hdr* hdrp, cap_data* datap) {
- return syscall(__NR_capget, hdrp, datap);
+ int res = syscall(__NR_capget, hdrp, datap);
+ if (res == 0) {
+ if (hdrp) MSAN_UNPOISON(hdrp, sizeof(*hdrp));
+ if (datap) MSAN_UNPOISON(datap, sizeof(*datap));
+ }
+ return res;
}
int sys_capset(cap_hdr* hdrp, const cap_data* datap) {
return syscall(__NR_capset, hdrp, datap);
}
+int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) {
+ int res;
+#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL)
+ // On 32-bit x86 or 32-bit arm, getresuid supports 16bit values only.
+ // Use getresuid32 instead.
+ res = syscall(__NR_getresuid32, ruid, euid, suid);
+#else
+ res = syscall(__NR_getresuid, ruid, euid, suid);
+#endif
+ if (res == 0) {
+ if (ruid) MSAN_UNPOISON(ruid, sizeof(*ruid));
+ if (euid) MSAN_UNPOISON(euid, sizeof(*euid));
+ if (suid) MSAN_UNPOISON(suid, sizeof(*suid));
+ }
+ return res;
+}
+
+int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) {
+ int res;
+#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL)
+ // On 32-bit x86 or 32-bit arm, getresgid supports 16bit values only.
+ // Use getresgid32 instead.
+ res = syscall(__NR_getresgid32, rgid, egid, sgid);
+#else
+ res = syscall(__NR_getresgid, rgid, egid, sgid);
+#endif
+ if (res == 0) {
+ if (rgid) MSAN_UNPOISON(rgid, sizeof(*rgid));
+ if (egid) MSAN_UNPOISON(egid, sizeof(*egid));
+ if (sgid) MSAN_UNPOISON(sgid, sizeof(*sgid));
+ }
+ return res;
+}
+
+int sys_chroot(const char* path) {
+ return syscall(__NR_chroot, path);
+}
+
+int sys_unshare(int flags) {
+ return syscall(__NR_unshare, flags);
+}
+
+int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) {
+ // In some toolchain (in particular Android and PNaCl toolchain),
+ // sigset_t is 32 bits, but Linux ABI requires 64 bits.
+ uint64_t linux_value = 0;
+ std::memcpy(&linux_value, set, std::min(sizeof(sigset_t), sizeof(uint64_t)));
+ return syscall(__NR_rt_sigprocmask, how, &linux_value, nullptr,
+ sizeof(linux_value));
+}
+
+#if defined(MEMORY_SANITIZER) || \
+ (defined(ARCH_CPU_X86_64) && defined(__GNUC__) && !defined(__clang__))
+// If MEMORY_SANITIZER is enabled, it is necessary to call sigaction() here,
+// rather than the direct syscall (sys_sigaction() defined by ourselves).
+// It is because, if MEMORY_SANITIZER is enabled, sigaction is wrapped, and
+// |act->sa_handler| is injected in order to unpoisonize the memory passed via
+// callback's arguments. Please see msan_interceptors.cc for more details.
+// So, if the direct syscall is used, as MEMORY_SANITIZER does not know about
+// it, sigaction() invocation in other places would be broken (in more precise,
+// returned |oldact| would have a broken |sa_handler| callback).
+// Practically, it would break NaCl's signal handler installation.
+// cf) native_client/src/trusted/service_runtime/linux/nacl_signal.c.
+//
+// Also on x86_64 architecture, we need naked function for rt_sigreturn.
+// However, there is no simple way to define it with GCC. Note that the body
+// of function is actually very small (only two instructions), but we need to
+// define much debug information in addition, otherwise backtrace() used by
+// base::StackTrace would not work so that some tests would fail.
+int sys_sigaction(int signum,
+ const struct sigaction* act,
+ struct sigaction* oldact) {
+ return sigaction(signum, act, oldact);
+}
+#else
+// struct sigaction is different ABI from the Linux's.
+struct KernelSigAction {
+ void (*kernel_handler)(int);
+ uint32_t sa_flags;
+ void (*sa_restorer)(void);
+ uint64_t sa_mask;
+};
+
+// On X86_64 arch, it is necessary to set sa_restorer always.
+#if defined(ARCH_CPU_X86_64)
+#if !defined(SA_RESTORER)
+#define SA_RESTORER 0x04000000
+#endif
+
+// rt_sigreturn is a special system call that interacts with the user land
+// stack. Thus, here prologue must not be created, which implies syscall()
+// does not work properly, too. Note that rt_sigreturn will never return.
+static __attribute__((naked)) void sys_rt_sigreturn() {
+ // Just invoke rt_sigreturn system call.
+ asm volatile ("syscall\n"
+ :: "a"(__NR_rt_sigreturn));
+}
+#endif
+
+int sys_sigaction(int signum,
+ const struct sigaction* act,
+ struct sigaction* oldact) {
+ KernelSigAction kernel_act = {};
+ if (act) {
+ kernel_act.kernel_handler = act->sa_handler;
+ std::memcpy(&kernel_act.sa_mask, &act->sa_mask,
+ std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask)));
+ kernel_act.sa_flags = act->sa_flags;
+
+#if defined(ARCH_CPU_X86_64)
+ if (!(kernel_act.sa_flags & SA_RESTORER)) {
+ kernel_act.sa_flags |= SA_RESTORER;
+ kernel_act.sa_restorer = sys_rt_sigreturn;
+ }
+#endif
+ }
+
+ KernelSigAction kernel_oldact = {};
+ int result = syscall(__NR_rt_sigaction, signum, act ? &kernel_act : nullptr,
+ oldact ? &kernel_oldact : nullptr, sizeof(uint64_t));
+ if (result == 0 && oldact) {
+ oldact->sa_handler = kernel_oldact.kernel_handler;
+ sigemptyset(&oldact->sa_mask);
+ std::memcpy(&oldact->sa_mask, &kernel_oldact.sa_mask,
+ std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask)));
+ oldact->sa_flags = kernel_oldact.sa_flags;
+ }
+ return result;
+}
+
+#endif // defined(MEMORY_SANITIZER)
+
} // namespace sandbox
diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h
index 28cc3a7..581425a 100644
--- a/sandbox/linux/services/syscall_wrappers.h
+++ b/sandbox/linux/services/syscall_wrappers.h
@@ -5,6 +5,7 @@
#ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
#define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
+#include <signal.h>
#include <stdint.h>
#include <sys/types.h>
@@ -56,6 +57,27 @@
SANDBOX_EXPORT int sys_capset(struct cap_hdr* hdrp,
const struct cap_data* datap);
+// Some libcs do not expose getresuid/getresgid wrappers.
+SANDBOX_EXPORT int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid);
+SANDBOX_EXPORT int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid);
+
+// Some libcs do not expose a chroot wrapper.
+SANDBOX_EXPORT int sys_chroot(const char* path);
+
+// Some libcs do not expose a unshare wrapper.
+SANDBOX_EXPORT int sys_unshare(int flags);
+
+// Some libcs do not expose a sigprocmask. Note that oldset must be a nullptr,
+// because of some ABI gap between toolchain's and Linux's.
+SANDBOX_EXPORT int sys_sigprocmask(int how,
+ const sigset_t* set,
+ decltype(nullptr) oldset);
+
+// Some libcs do not expose a sigaction().
+SANDBOX_EXPORT int sys_sigaction(int signum,
+ const struct sigaction* act,
+ struct sigaction* oldact);
+
} // namespace sandbox
#endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc
index a8b48fe..1878ff3 100644
--- a/sandbox/linux/services/syscall_wrappers_unittest.cc
+++ b/sandbox/linux/services/syscall_wrappers_unittest.cc
@@ -8,11 +8,13 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <cstring>
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/third_party/valgrind/valgrind.h"
#include "build/build_config.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,6 +62,38 @@
EXPECT_EQ(kSuccessExit, WEXITSTATUS(status));
}
+TEST(SyscallWrappers, GetRESUid) {
+ uid_t ruid, euid, suid;
+ uid_t sys_ruid, sys_euid, sys_suid;
+ ASSERT_EQ(0, getresuid(&ruid, &euid, &suid));
+ ASSERT_EQ(0, sys_getresuid(&sys_ruid, &sys_euid, &sys_suid));
+ EXPECT_EQ(ruid, sys_ruid);
+ EXPECT_EQ(euid, sys_euid);
+ EXPECT_EQ(suid, sys_suid);
+}
+
+TEST(SyscallWrappers, GetRESGid) {
+ gid_t rgid, egid, sgid;
+ gid_t sys_rgid, sys_egid, sys_sgid;
+ ASSERT_EQ(0, getresgid(&rgid, &egid, &sgid));
+ ASSERT_EQ(0, sys_getresgid(&sys_rgid, &sys_egid, &sys_sgid));
+ EXPECT_EQ(rgid, sys_rgid);
+ EXPECT_EQ(egid, sys_egid);
+ EXPECT_EQ(sgid, sys_sgid);
+}
+
+TEST(SyscallWrappers, LinuxSigSet) {
+ sigset_t sigset;
+ ASSERT_EQ(0, sigemptyset(&sigset));
+ ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGSEGV));
+ ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGBUS));
+ uint64_t linux_sigset = 0;
+ std::memcpy(&linux_sigset, &sigset,
+ std::min(sizeof(sigset), sizeof(linux_sigset)));
+ EXPECT_EQ((1ULL << (LINUX_SIGSEGV - 1)) | (1ULL << (LINUX_SIGBUS - 1)),
+ linux_sigset);
+}
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/services/thread_helpers.cc b/sandbox/linux/services/thread_helpers.cc
index f80c8a8..80766a9 100644
--- a/sandbox/linux/services/thread_helpers.cc
+++ b/sandbox/linux/services/thread_helpers.cc
@@ -13,7 +13,6 @@
#include <string>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/scoped_file.h"
diff --git a/sandbox/linux/services/thread_helpers.h b/sandbox/linux/services/thread_helpers.h
index 2915784..f4abdff 100644
--- a/sandbox/linux/services/thread_helpers.h
+++ b/sandbox/linux/services/thread_helpers.h
@@ -5,7 +5,7 @@
#ifndef SANDBOX_LINUX_SERVICES_THREAD_HELPERS_H_
#define SANDBOX_LINUX_SERVICES_THREAD_HELPERS_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "sandbox/sandbox_export.h"
namespace base { class Thread; }
diff --git a/sandbox/linux/services/thread_helpers_unittests.cc b/sandbox/linux/services/thread_helpers_unittests.cc
index 8886516..7357a0c 100644
--- a/sandbox/linux/services/thread_helpers_unittests.cc
+++ b/sandbox/linux/services/thread_helpers_unittests.cc
@@ -10,7 +10,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
diff --git a/sandbox/linux/services/yama.h b/sandbox/linux/services/yama.h
index 20c28ba..e6c5c45 100644
--- a/sandbox/linux/services/yama.h
+++ b/sandbox/linux/services/yama.h
@@ -5,8 +5,7 @@
#ifndef SANDBOX_LINUX_SERVICES_YAMA_H_
#define SANDBOX_LINUX_SERVICES_YAMA_H_
-#include "base/basictypes.h"
-#include "base/process/process_handle.h"
+#include "base/macros.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
diff --git a/sandbox/linux/syscall_broker/broker_process.h b/sandbox/linux/syscall_broker/broker_process.h
index c23ac3c..8a512a0 100644
--- a/sandbox/linux/syscall_broker/broker_process.h
+++ b/sandbox/linux/syscall_broker/broker_process.h
@@ -8,8 +8,8 @@
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/callback_forward.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/process/process.h"
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc
index ee284f2..bd7ef27 100644
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -17,7 +17,6 @@
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
diff --git a/sandbox/linux/system_headers/android_arm_ucontext.h b/sandbox/linux/system_headers/android_arm_ucontext.h
deleted file mode 100644
index a380499..0000000
--- a/sandbox/linux/system_headers/android_arm_ucontext.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
-
-#if !defined(__BIONIC_HAVE_UCONTEXT_T)
-#include <asm/sigcontext.h>
-
-// We also need greg_t for the sandbox, include it in this header as well.
-typedef unsigned long greg_t;
-
-//typedef unsigned long sigset_t;
-typedef struct ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext uc_mcontext;
- sigset_t uc_sigmask;
- /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */
- int __not_used[32 - (sizeof (sigset_t) / sizeof (int))];
- /* Last for extensibility. Eight byte aligned because some
- coprocessors require eight byte alignment. */
- unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
-} ucontext_t;
-
-#else
-#include <sys/ucontext.h>
-#endif // __BIONIC_HAVE_UCONTEXT_T
-
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_ucontext.h b/sandbox/linux/system_headers/android_ucontext.h
deleted file mode 100644
index 8e873be..0000000
--- a/sandbox/linux/system_headers/android_ucontext.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
-
-#if defined(__ANDROID__)
-
-#if defined(__arm__)
-#include "sandbox/linux/system_headers/android_arm_ucontext.h"
-#elif defined(__i386__)
-#include "sandbox/linux/system_headers/android_i386_ucontext.h"
-#elif defined(__x86_64__)
-#include "sandbox/linux/system_headers/android_x86_64_ucontext.h"
-#elif defined(__mips__)
-#include "sandbox/linux/system_headers/android_mips_ucontext.h"
-#elif defined(__aarch64__)
-#include "sandbox/linux/system_headers/android_arm64_ucontext.h"
-#else
-#error "No support for your architecture in Android header"
-#endif
-
-#else // __ANDROID__
-#error "Android header file included on non Android."
-#endif // __ANDROID__
-
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_arm64_ucontext.h b/sandbox/linux/system_headers/arm64_linux_ucontext.h
similarity index 78%
rename from sandbox/linux/system_headers/android_arm64_ucontext.h
rename to sandbox/linux/system_headers/arm64_linux_ucontext.h
index df2b66a..46e0407 100644
--- a/sandbox/linux/system_headers/android_arm64_ucontext.h
+++ b/sandbox/linux/system_headers/arm64_linux_ucontext.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_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
#if !defined(__BIONIC_HAVE_UCONTEXT_T)
#include <asm/sigcontext.h>
@@ -26,4 +26,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/arm_linux_syscalls.h b/sandbox/linux/system_headers/arm_linux_syscalls.h
index b11041d..bfd5342 100644
--- a/sandbox/linux/system_headers/arm_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm_linux_syscalls.h
@@ -10,8 +10,10 @@
#error "Including header on wrong architecture"
#endif
-// __NR_SYSCALL_BASE, __ARM_NR_BASE are defined in <asm/unistd.h>.
-#include <asm/unistd.h>
+#if !defined(__NR_SYSCALL_BASE)
+// On ARM EABI arch, __NR_SYSCALL_BASE is 0.
+#define __NR_SYSCALL_BASE 0
+#endif
// This syscall list has holes, because ARM EABI makes some syscalls obsolete.
@@ -1380,6 +1382,10 @@
#endif
// ARM private syscalls.
+#if !defined(__ARM_NR_BASE)
+#define __ARM_NR_BASE (__NR_SYSCALL_BASE + 0xF0000)
+#endif
+
#if !defined(__ARM_NR_breakpoint)
#define __ARM_NR_breakpoint (__ARM_NR_BASE+1)
#endif
@@ -1406,4 +1412,3 @@
#endif
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_
-
diff --git a/sandbox/linux/system_headers/arm_linux_ucontext.h b/sandbox/linux/system_headers/arm_linux_ucontext.h
new file mode 100644
index 0000000..0eb723a
--- /dev/null
+++ b/sandbox/linux/system_headers/arm_linux_ucontext.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
+
+#if !defined(__BIONIC_HAVE_UCONTEXT_T)
+#if !defined(__native_client_nonsfi__)
+#include <asm/sigcontext.h>
+#else
+// In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare
+// them.
+struct sigcontext {
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long arm_r0;
+ unsigned long arm_r1;
+ unsigned long arm_r2;
+ unsigned long arm_r3;
+ unsigned long arm_r4;
+ unsigned long arm_r5;
+ unsigned long arm_r6;
+ unsigned long arm_r7;
+ unsigned long arm_r8;
+ unsigned long arm_r9;
+ unsigned long arm_r10;
+ unsigned long arm_fp;
+ unsigned long arm_ip;
+ unsigned long arm_sp;
+ unsigned long arm_lr;
+ unsigned long arm_pc;
+ unsigned long arm_cpsr;
+ unsigned long fault_address;
+};
+
+typedef struct sigaltstack {
+ void* ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#endif
+
+// We also need greg_t for the sandbox, include it in this header as well.
+typedef unsigned long greg_t;
+
+// typedef unsigned long sigset_t;
+typedef struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext* uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+ /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */
+ int __not_used[32 - (sizeof(sigset_t) / sizeof(int))];
+ /* Last for extensibility. Eight byte aligned because some
+ coprocessors require eight byte alignment. */
+ unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
+} ucontext_t;
+
+#else
+#include <sys/ucontext.h>
+#endif // __BIONIC_HAVE_UCONTEXT_T
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_i386_ucontext.h b/sandbox/linux/system_headers/i386_linux_ucontext.h
similarity index 81%
rename from sandbox/linux/system_headers/android_i386_ucontext.h
rename to sandbox/linux/system_headers/i386_linux_ucontext.h
index 868016b..61d9f7a 100644
--- a/sandbox/linux/system_headers/android_i386_ucontext.h
+++ b/sandbox/linux/system_headers/i386_linux_ucontext.h
@@ -11,7 +11,16 @@
// except we do use sigset_t for uc_sigmask instead of a custom type.
#if !defined(__BIONIC_HAVE_UCONTEXT_T)
+#if !defined(__native_client_nonsfi__)
#include <asm/sigcontext.h>
+#else
+// In PNaCl toolchain, sigcontext is not defined. So here declare it.
+typedef struct sigaltstack {
+ void* ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+#endif
/* 80-bit floating-point register */
struct _libc_fpreg {
@@ -68,7 +77,12 @@
struct ucontext* uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
- sigset_t uc_sigmask;
+ // Android and PNaCl toolchain's sigset_t has only 32 bits, though Linux
+ // ABI requires 64 bits.
+ union {
+ sigset_t uc_sigmask;
+ uint32_t kernel_sigmask[2];
+ };
struct _libc_fpstate __fpregs_mem;
} ucontext_t;
diff --git a/sandbox/linux/system_headers/linux_filter.h b/sandbox/linux/system_headers/linux_filter.h
new file mode 100644
index 0000000..b23b6eb
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_filter.h
@@ -0,0 +1,140 @@
+// 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_SYSTEM_HEADERS_LINUX_FILTER_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_
+
+#include <stdint.h>
+
+// The following structs and macros are taken from linux/filter.h,
+// as some toolchain does not expose them.
+struct sock_filter {
+ uint16_t code;
+ uint8_t jt;
+ uint8_t jf;
+ uint32_t k;
+};
+
+struct sock_fprog {
+ uint16_t len;
+ struct sock_filter *filter;
+};
+
+#ifndef BPF_CLASS
+#define BPF_CLASS(code) ((code) & 0x07)
+#endif
+
+#ifndef BPF_LD
+#define BPF_LD 0x00
+#endif
+
+#ifndef BPF_ALU
+#define BPF_ALU 0x04
+#endif
+
+#ifndef BPF_JMP
+#define BPF_JMP 0x05
+#endif
+
+#ifndef BPF_RET
+#define BPF_RET 0x06
+#endif
+
+#ifndef BPF_SIZE
+#define BPF_SIZE(code) ((code) & 0x18)
+#endif
+
+#ifndef BPF_W
+#define BPF_W 0x00
+#endif
+
+#ifndef BPF_MODE
+#define BPF_MODE(code) ((code) & 0xe0)
+#endif
+
+#ifndef BPF_ABS
+#define BPF_ABS 0x20
+#endif
+
+#ifndef BPF_OP
+#define BPF_OP(code) ((code) & 0xf0)
+#endif
+
+#ifndef BPF_ADD
+#define BPF_ADD 0x00
+#endif
+
+#ifndef BPF_SUB
+#define BPF_SUB 0x10
+#endif
+
+#ifndef BPF_MUL
+#define BPF_MUL 0x20
+#endif
+
+#ifndef BPF_DIV
+#define BPF_DIV 0x30
+#endif
+
+#ifndef BPF_OR
+#define BPF_OR 0x40
+#endif
+
+#ifndef BPF_AND
+#define BPF_AND 0x50
+#endif
+
+#ifndef BPF_LSH
+#define BPF_LSH 0x60
+#endif
+
+#ifndef BPF_RSH
+#define BPF_RSH 0x70
+#endif
+
+#ifndef BPF_NEG
+#define BPF_NEG 0x80
+#endif
+
+#ifndef BPF_MOD
+#define BPF_MOD 0x90
+#endif
+
+#ifndef BPF_XOR
+#define BPF_XOR 0xA0
+#endif
+
+#ifndef BPF_JA
+#define BPF_JA 0x00
+#endif
+
+#ifndef BPF_JEQ
+#define BPF_JEQ 0x10
+#endif
+
+#ifndef BPF_JGT
+#define BPF_JGT 0x20
+#endif
+
+#ifndef BPF_JGE
+#define BPF_JGE 0x30
+#endif
+
+#ifndef BPF_JSET
+#define BPF_JSET 0x40
+#endif
+
+#ifndef BPF_SRC
+#define BPF_SRC(code) ((code) & 0x08)
+#endif
+
+#ifndef BPF_K
+#define BPF_K 0x00
+#endif
+
+#ifndef BPF_MAXINSNS
+#define BPF_MAXINSNS 4096
+#endif
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_
diff --git a/sandbox/linux/system_headers/android_futex.h b/sandbox/linux/system_headers/linux_futex.h
similarity index 88%
rename from sandbox/linux/system_headers/android_futex.h
rename to sandbox/linux/system_headers/linux_futex.h
index 11b766f..91733a8 100644
--- a/sandbox/linux/system_headers/android_futex.h
+++ b/sandbox/linux/system_headers/linux_futex.h
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
+
+#include <linux/futex.h>
#if !defined(FUTEX_WAIT)
#define FUTEX_WAIT 0
@@ -77,4 +79,4 @@
#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
#endif
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
diff --git a/sandbox/linux/system_headers/linux_seccomp.h b/sandbox/linux/system_headers/linux_seccomp.h
index 40029c8..3deb3d2 100644
--- a/sandbox/linux/system_headers/linux_seccomp.h
+++ b/sandbox/linux/system_headers/linux_seccomp.h
@@ -5,8 +5,6 @@
#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
-#include <linux/filter.h>
-
// The Seccomp2 kernel ABI is not part of older versions of glibc.
// As we can't break compilation with these versions of the library,
// we explicitly define all missing symbols.
@@ -67,13 +65,6 @@
#define IPC_64 0x0100
#endif
-#ifndef BPF_MOD
-#define BPF_MOD 0x90
-#endif
-#ifndef BPF_XOR
-#define BPF_XOR 0xA0
-#endif
-
// In order to build will older tool chains, we currently have to avoid
// including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on
// our own definitions of the seccomp kernel ABI.
diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h
new file mode 100644
index 0000000..5db7fc5
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_signal.h
@@ -0,0 +1,73 @@
+// 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_SYSTEM_HEADERS_LINUX_SIGNAL_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
+
+// NOTE: On some toolchains, signal related ABI is incompatible with Linux's
+// (not undefined, but defined different values and in different memory
+// layouts). So, fill the gap here.
+
+#if defined(__native_client_nonsfi__)
+#if !defined(__i386__) && !defined(__arm__)
+#error "Unsupported platform"
+#endif
+
+#include <signal.h>
+
+#define LINUX_SIGBUS 7 // 10 in PNaCl toolchain.
+#define LINUX_SIGSEGV 11 // 11 in PNaCl toolchain. Defined for consistency.
+#define LINUX_SIGCHLD 17 // 20 in PNaCl toolchain.
+#define LINUX_SIGSYS 31 // 12 in PNaCl toolchain.
+
+#define LINUX_SIG_BLOCK 0 // 1 in PNaCl toolchain.
+#define LINUX_SIG_UNBLOCK 1 // 2 in PNaCl toolchain.
+
+#define LINUX_SA_SIGINFO 4 // 2 in PNaCl toolchain.
+#define LINUX_SA_NODEFER 0x40000000 // Undefined in PNaCl toolchain.
+#define LINUX_SA_RESTART 0x10000000 // Undefined in PNaCl toolchain.
+
+#define LINUX_SIG_DFL 0 // In PNaCl toolchain, unneeded cast is applied.
+
+struct LinuxSigInfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+
+ // Extra data is followed by the |si_code|. The length depends on the
+ // signal number.
+ char _sifields[1];
+};
+
+#include "sandbox/linux/system_headers/linux_ucontext.h"
+
+#else // !defined(__native_client_nonsfi__)
+
+// Just alias the toolchain's value.
+#include <signal.h>
+
+#define LINUX_SIGBUS SIGBUS
+#define LINUX_SIGSEGV SIGSEGV
+#define LINUX_SIGCHLD SIGCHLD
+#define LINUX_SIGSYS SIGSYS
+
+#define LINUX_SIG_BLOCK SIG_BLOCK
+#define LINUX_SIG_UNBLOCK SIG_UNBLOCK
+
+#define LINUX_SA_SIGINFO SA_SIGINFO
+#define LINUX_SA_NODEFER SA_NODEFER
+#define LINUX_SA_RESTART SA_RESTART
+
+#define LINUX_SIG_DFL SIG_DFL
+
+typedef siginfo_t LinuxSigInfo;
+
+#if defined(__ANDROID__)
+// Android's signal.h doesn't define ucontext etc.
+#include "sandbox/linux/system_headers/linux_ucontext.h"
+#endif // defined(__ANDROID__)
+
+#endif // !defined(__native_client_nonsfi__)
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h
new file mode 100644
index 0000000..ea4d8a6
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_ucontext.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
+
+#if defined(__ANDROID__) || defined(__native_client_nonsfi__)
+
+#if defined(__arm__)
+#include "sandbox/linux/system_headers/arm_linux_ucontext.h"
+#elif defined(__i386__)
+#include "sandbox/linux/system_headers/i386_linux_ucontext.h"
+#elif defined(__x86_64__)
+#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h"
+#elif defined(__mips__)
+#include "sandbox/linux/system_headers/mips_linux_ucontext.h"
+#elif defined(__aarch64__)
+#include "sandbox/linux/system_headers/arm64_linux_ucontext.h"
+#else
+#error "No support for your architecture in Android or PNaCl header"
+#endif
+
+#else // defined(__ANDROID__) || defined(__native_client_nonsfi__)
+#error "The header file included on non Android and non PNaCl."
+#endif // defined(__ANDROID__) || defined(__native_client_nonsfi__)
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_mips_ucontext.h b/sandbox/linux/system_headers/mips_linux_ucontext.h
similarity index 86%
rename from sandbox/linux/system_headers/android_mips_ucontext.h
rename to sandbox/linux/system_headers/mips_linux_ucontext.h
index ec3aa63..27b3763 100644
--- a/sandbox/linux/system_headers/android_mips_ucontext.h
+++ b/sandbox/linux/system_headers/mips_linux_ucontext.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_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
// This is mostly copied from breakpad (common/android/include/sys/ucontext.h),
// except we do use sigset_t for uc_sigmask instead of a custom type.
@@ -48,4 +48,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_x86_64_ucontext.h b/sandbox/linux/system_headers/x86_64_linux_ucontext.h
similarity index 89%
rename from sandbox/linux/system_headers/android_x86_64_ucontext.h
rename to sandbox/linux/system_headers/x86_64_linux_ucontext.h
index 778e6d0..57b8919 100644
--- a/sandbox/linux/system_headers/android_x86_64_ucontext.h
+++ b/sandbox/linux/system_headers/x86_64_linux_ucontext.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_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
// We do something compatible with glibc. Hopefully, at some point Android will
// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined.
@@ -85,4 +85,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/tests/sandbox_test_runner.h b/sandbox/linux/tests/sandbox_test_runner.h
index 3504126..3155b74 100644
--- a/sandbox/linux/tests/sandbox_test_runner.h
+++ b/sandbox/linux/tests/sandbox_test_runner.h
@@ -5,7 +5,7 @@
#ifndef SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
#define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
namespace sandbox {
diff --git a/sandbox/linux/tests/sandbox_test_runner_function_pointer.h b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
index f2554f7..cadd07c 100644
--- a/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
+++ b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
@@ -5,7 +5,7 @@
#ifndef SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
#define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "sandbox/linux/tests/sandbox_test_runner.h"
namespace sandbox {
diff --git a/sandbox/linux/tests/test_utils.cc b/sandbox/linux/tests/test_utils.cc
index 6000b8a..747bad2 100644
--- a/sandbox/linux/tests/test_utils.cc
+++ b/sandbox/linux/tests/test_utils.cc
@@ -10,7 +10,6 @@
#include <sys/wait.h>
#include <unistd.h>
-#include "base/basictypes.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
diff --git a/sandbox/linux/tests/test_utils.h b/sandbox/linux/tests/test_utils.h
index 1d9eb79..7cf9749 100644
--- a/sandbox/linux/tests/test_utils.h
+++ b/sandbox/linux/tests/test_utils.h
@@ -7,7 +7,7 @@
#include <sys/types.h>
-#include "base/basictypes.h"
+#include "base/macros.h"
namespace sandbox {
diff --git a/sandbox/linux/tests/unit_tests.h b/sandbox/linux/tests/unit_tests.h
index bf0a44f..5a7116e 100644
--- a/sandbox/linux/tests/unit_tests.h
+++ b/sandbox/linux/tests/unit_tests.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
-#define SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
+#ifndef SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
+#define SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "build/build_config.h"
#include "sandbox/linux/tests/sandbox_test_runner_function_pointer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -198,4 +198,4 @@
} // namespace
-#endif // SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
+#endif // SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
index f160260..18e4050 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
@@ -40,7 +40,7 @@
* Initializes Java-side utils.
*/
private void initializeJavaUtils() {
- PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+ PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX, getApplicationContext());
}
/**
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 807b8da..e130479 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -13,7 +13,7 @@
}
skia_support_gpu = !is_ios
-skia_support_pdf = !is_ios && (enable_basic_printing || enable_print_preview)
+skia_support_pdf = false
# The list of Skia defines that are to be set for chromium.
gypi_skia_defines =
diff --git a/skia/ext/SkDiscardableMemory_chrome.cc b/skia/ext/SkDiscardableMemory_chrome.cc
index 5bb6928..1a98720 100644
--- a/skia/ext/SkDiscardableMemory_chrome.cc
+++ b/skia/ext/SkDiscardableMemory_chrome.cc
@@ -14,7 +14,7 @@
}
void* SkDiscardableMemoryChrome::data() {
- return discardable_->Memory();
+ return discardable_->data();
}
void SkDiscardableMemoryChrome::unlock() {
diff --git a/sky/engine/bindings/BUILD.gn b/sky/engine/bindings/BUILD.gn
index 0e8edf2..b7dbafe 100644
--- a/sky/engine/bindings/BUILD.gn
+++ b/sky/engine/bindings/BUILD.gn
@@ -89,7 +89,7 @@
"--output_bin",
rebase_path(isolate_snapshot, root_build_dir),
"--target_os",
- os,
+ target_os,
"--url_mapping=dart:sky,$dart_sky_path",
"--url_mapping=dart:mojo.internal,$internal_path",
"--url_mapping=dart:sky_builtin,$builtin_path",
diff --git a/sky/shell/org/domokit/sky/shell/SkyApplication.java b/sky/shell/org/domokit/sky/shell/SkyApplication.java
index 54798de..0fd9294 100644
--- a/sky/shell/org/domokit/sky/shell/SkyApplication.java
+++ b/sky/shell/org/domokit/sky/shell/SkyApplication.java
@@ -39,7 +39,7 @@
}
private void initializeJavaUtils() {
- PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+ PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX, getApplicationContext());
}
private void initializeNative() {
diff --git a/testing/android/junit/BUILD.gn b/testing/android/junit/BUILD.gn
index f80d0b5..d479629 100644
--- a/testing/android/junit/BUILD.gn
+++ b/testing/android/junit/BUILD.gn
@@ -8,20 +8,17 @@
# GYP: //testing/android/junit_test.gyp:junit_test_support
java_library("junit_test_support") {
+ testonly = true
DEPRECATED_java_in_dir = "java/src"
deps = [
"//third_party/junit",
"//third_party/mockito:mockito_java",
"//third_party/robolectric:robolectric_java",
+ "//third_party/robolectric:android-all-4.3_r2-robolectric-0",
]
}
# GYP: //testing/android/junit_test.gyp:junit_unit_tests
-java_binary("junit_unittests") {
- deps = [
- ":junit_test_support",
- "//third_party/junit",
- ]
- main_class = "org.chromium.testing.local.JunitTestMain"
+junit_binary("junit_unittests") {
DEPRECATED_java_in_dir = "javatests/src"
}
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java b/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java
new file mode 100644
index 0000000..3d501b3
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java
@@ -0,0 +1,54 @@
+// 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.
+
+package org.chromium.testing.local;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/** A json RunListener that creates a Json file with test run information.
+ */
+public class JsonListener extends RunListener {
+
+ private final JsonLogger mJsonLogger;
+ private long mTestStartTimeMillis;
+ private boolean mCurrentTestPassed;
+
+ public JsonListener(JsonLogger jsonLogger) {
+ mJsonLogger = jsonLogger;
+ }
+
+ /** Called after all tests run.
+ */
+ @Override
+ public void testRunFinished(Result r) throws Exception {
+ mJsonLogger.writeJsonToFile();
+ }
+
+ /** Called when a test is about to start.
+ */
+ @Override
+ public void testStarted(Description d) throws Exception {
+ mCurrentTestPassed = true;
+ mTestStartTimeMillis = System.currentTimeMillis();
+ }
+
+ /** Called when a test has just finished.
+ */
+ @Override
+ public void testFinished(Description d) throws Exception {
+ long testElapsedTimeMillis = System.currentTimeMillis() - mTestStartTimeMillis;
+ mJsonLogger.addTestResultInfo(d, mCurrentTestPassed, testElapsedTimeMillis);
+ }
+
+ /** Called when a test fails.
+ */
+ @Override
+ public void testFailure(Failure f) throws Exception {
+ mCurrentTestPassed = false;
+ }
+}
+
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java b/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java
new file mode 100644
index 0000000..c253ba3
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java
@@ -0,0 +1,89 @@
+// 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.
+
+package org.chromium.testing.local;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.runner.Description;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+/**
+ * Creates json file with junit test information. Format of the json file mirrors the
+ * json generated by build/android/pylib/results/json_results.py.
+ */
+public class JsonLogger {
+
+ private final JSONObject mBaseJsonObject;
+ private final JSONObject mBaseTestInfoJsonObject;
+ private final File mOutputFile;
+
+ public JsonLogger(File outputFile) {
+ mBaseJsonObject = new JSONObject();
+ mBaseTestInfoJsonObject = new JSONObject();
+ mOutputFile = outputFile;
+
+ try {
+ mBaseJsonObject.put("global_tags", new JSONArray());
+ mBaseJsonObject.put("all_tests", new JSONArray());
+ mBaseJsonObject.put("disabled_tests", new JSONArray());
+ mBaseJsonObject.put("per_iteration_data",
+ new JSONArray().put(mBaseTestInfoJsonObject));
+ } catch (JSONException e) {
+ System.err.println("Unable to create json output.");
+ }
+ }
+
+ /**
+ * Add the results of a test run to the json output.
+ */
+ public void addTestResultInfo(Description test, boolean passed, long elapsedTimeMillis) {
+ JSONObject testInfoJsonObject = new JSONObject();
+
+ try {
+ testInfoJsonObject.put("status", (passed ? "SUCCESS" : "FAILURE"));
+ testInfoJsonObject.put("elapsed_time_ms", elapsedTimeMillis);
+ testInfoJsonObject.put("output_snippet", "");
+ testInfoJsonObject.put("output_snippet_base64", "");
+ testInfoJsonObject.put("losless_snippet", "");
+
+ if (mBaseTestInfoJsonObject.optJSONArray(testName(test)) == null) {
+ mBaseTestInfoJsonObject.put(testName(test), new JSONArray());
+ mBaseJsonObject.getJSONArray("all_tests").put(testName(test));
+ }
+ mBaseTestInfoJsonObject.getJSONArray(testName(test)).put(testInfoJsonObject);
+ } catch (JSONException e) {
+ System.err.println("Unable to log test to json output: " + testName(test));
+ }
+ }
+
+ /**
+ * Writes the json output to a file.
+ */
+ public void writeJsonToFile() {
+ try {
+ PrintStream stream = new PrintStream(new FileOutputStream(mOutputFile));
+ try {
+ stream.print(mBaseJsonObject);
+ } finally {
+ try {
+ stream.close();
+ } catch (RuntimeException e) {
+ System.err.println("Unable to close output file: " + mOutputFile.getPath());
+ }
+ }
+ } catch (FileNotFoundException e) {
+ System.err.println("File not found: " + mOutputFile.getPath());
+ }
+ }
+
+ private String testName(Description test) {
+ return test.getClassName() + "#" + test.getMethodName();
+ }
+}
\ No newline at end of file
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
index 9de7874..20c5a65 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
@@ -4,17 +4,23 @@
package org.chromium.testing.local;
+import java.io.File;
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Pattern;
/**
* Parses command line arguments for JunitTestMain.
*/
public class JunitTestArgParser {
+ private static final Pattern COLON = Pattern.compile(":");
+
private final Set<String> mPackageFilters;
private final Set<Class<?>> mRunnerFilters;
private final Set<String> mGtestFilters;
+ private File mJsonOutput;
+ private String[] mTestJars;
public static JunitTestArgParser parse(String[] args) {
@@ -38,6 +44,12 @@
} else if ("gtest-filter".equals(argName)) {
// Read the command line argument after the flag.
parsed.addGtestFilter(args[++i]);
+ } else if ("json-results-file".equals(argName)) {
+ // Read the command line argument after the flag.
+ parsed.setJsonOutputFile(args[++i]);
+ } else if ("test-jars".equals(argName)) {
+ // Read the command line argument after the flag.
+ parsed.setTestJars(args[++i]);
} else {
System.out.println("Ignoring flag: \"" + argName + "\"");
}
@@ -60,6 +72,7 @@
mPackageFilters = new HashSet<String>();
mRunnerFilters = new HashSet<Class<?>>();
mGtestFilters = new HashSet<String>();
+ mJsonOutput = null;
}
public Set<String> getPackageFilters() {
@@ -74,6 +87,14 @@
return mGtestFilters;
}
+ public File getJsonOutputFile() {
+ return mJsonOutput;
+ }
+
+ public String[] getTestJars() {
+ return mTestJars;
+ }
+
private void addPackageFilter(String packageFilter) {
mPackageFilters.add(packageFilter);
}
@@ -86,5 +107,11 @@
mGtestFilters.add(gtestFilter);
}
-}
+ private void setJsonOutputFile(String path) {
+ mJsonOutput = new File(path);
+ }
+ private void setTestJars(String jars) {
+ mTestJars = COLON.split(jars);
+ }
+}
\ No newline at end of file
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
index d9c468d..f32579b 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
@@ -9,8 +9,9 @@
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.LinkedList;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
@@ -32,10 +33,19 @@
/**
* Finds all classes on the class path annotated with RunWith.
*/
- public static Class[] findClassesFromClasspath() {
+ public static Class[] findClassesFromClasspath(String[] testJars) {
String[] jarPaths = COLON.split(System.getProperty("java.class.path"));
- LinkedList<Class> classes = new LinkedList<Class>();
- for (String jp : jarPaths) {
+ List<String> testJarPaths = new ArrayList<String>(testJars.length);
+ for (String testJar: testJars) {
+ for (String jarPath: jarPaths) {
+ if (jarPath.endsWith(testJar)) {
+ testJarPaths.add(jarPath);
+ break;
+ }
+ }
+ }
+ List<Class> classes = new ArrayList<Class>();
+ for (String jp : testJarPaths) {
try {
JarFile jf = new JarFile(jp);
for (Enumeration<JarEntry> eje = jf.entries(); eje.hasMoreElements();) {
@@ -48,7 +58,7 @@
cn = FORWARD_SLASH.matcher(cn).replaceAll(".");
Class<?> c = classOrNull(cn);
if (c != null && c.isAnnotationPresent(RunWith.class)) {
- classes.push(c);
+ classes.add(c);
}
}
jf.close();
@@ -76,10 +86,13 @@
JunitTestArgParser parser = JunitTestArgParser.parse(args);
JUnitCore core = new JUnitCore();
- GtestLogger logger = new GtestLogger(System.out);
- core.addListener(new GtestListener(logger));
- Class[] classes = findClassesFromClasspath();
- Request testRequest = Request.classes(new GtestComputer(logger), classes);
+ GtestLogger gtestLogger = new GtestLogger(System.out);
+ core.addListener(new GtestListener(gtestLogger));
+ JsonLogger jsonLogger = new JsonLogger(parser.getJsonOutputFile());
+ core.addListener(new JsonListener(jsonLogger));
+ Class[] classes = findClassesFromClasspath(parser.getTestJars());
+ Request testRequest = Request.classes(new GtestComputer(gtestLogger), classes);
+
for (String packageFilter : parser.getPackageFilters()) {
testRequest = testRequest.filterWith(new PackageFilter(packageFilter));
}
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
index 293525e..cf6202b 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
@@ -8,13 +8,10 @@
import org.robolectric.AndroidManifest;
import org.robolectric.DependencyResolver;
-import org.robolectric.LocalDependencyResolver;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.SdkConfig;
import org.robolectric.annotation.Config;
-import java.io.File;
-
/**
* A custom Robolectric Junit4 Test Runner. This test runner will load the
* "real" android jars from a local directory rather than use Maven to fetch
@@ -32,13 +29,7 @@
@Override
protected final DependencyResolver getJarResolver() {
- String dependencyDir = System.getProperty("robolectric.dependency.dir");
- if (dependencyDir == null) {
- throw new IllegalStateException("robolectric.dependency.dir not specified. Make sure"
- + " you are setting the robolectric.dependency.dir system property to the"
- + " directory containing Robolectric's runtime dependency jars.");
- }
- return new LocalDependencyResolver(new File(dependencyDir));
+ return new RobolectricClasspathDependencyResolver();
}
@Override
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java b/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java
new file mode 100644
index 0000000..47bc1ba
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java
@@ -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.
+
+package org.chromium.testing.local;
+
+import org.robolectric.DependencyJar;
+import org.robolectric.DependencyResolver;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.regex.Pattern;
+
+/**
+ * A Robolectric dependency resolver that looks for the Robolectric dependencies
+ * in the Java classpath.
+ */
+public class RobolectricClasspathDependencyResolver implements DependencyResolver {
+ private static final Pattern COLON = Pattern.compile(":");
+ private final String[] mClassPathJars;
+
+ /**
+ * Creates a {@link ClasspathDependencyResolver}.
+ */
+ public RobolectricClasspathDependencyResolver() {
+ mClassPathJars = COLON.split(System.getProperty("java.class.path"));
+ }
+
+ /**
+ * Returns the {@link URL} for a Robolectric dependency. It looks through the jars
+ * in the classpath to find the dependency's filepath.
+ */
+ @Override
+ public URL getLocalArtifactUrl(DependencyJar dependency) {
+ // Jar filenames are constructed identically to how they are built in Robolectric's
+ // own LocalDependencyResolver.
+ String dependencyJar = dependency.getArtifactId() + "-" + dependency.getVersion() + "."
+ + dependency.getType();
+
+ for (String jarPath : mClassPathJars) {
+ if (jarPath.endsWith(dependencyJar)) {
+ return fileToUrl(new File(jarPath));
+ }
+ }
+ throw new IllegalStateException(
+ String.format("Robolectric jar %s was not found in classpath.", dependencyJar));
+ }
+
+ /**
+ * Returns the {@link URL} for a list of Robolectric dependencies.
+ */
+ @Override
+ public URL[] getLocalArtifactUrls(DependencyJar... dependencies) {
+ URL[] urls = new URL[dependencies.length];
+
+ for (int i = 0; i < dependencies.length; i++) {
+ urls[i] = getLocalArtifactUrl(dependencies[i]);
+ }
+
+ return urls;
+ }
+
+ private static URL fileToUrl(File file) {
+ try {
+ return file.toURI().toURL();
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(
+ String.format("File \"%s\" cannot be represented as a URL: %s", file, e));
+ }
+ }
+}
\ No newline at end of file
diff --git a/testing/android/native_test.gyp b/testing/android/native_test.gyp
index 632d687..b26e01e 100644
--- a/testing/android/native_test.gyp
+++ b/testing/android/native_test.gyp
@@ -12,9 +12,9 @@
'message': 'building native pieces of native test package',
'type': 'static_library',
'sources': [
- 'native_test_jni_onload.cc',
- 'native_test_launcher.cc',
- 'native_test_launcher.h',
+ 'native_test/native_test_jni_onload.cc',
+ 'native_test/native_test_launcher.cc',
+ 'native_test/native_test_launcher.h',
],
'dependencies': [
'../../base/base.gyp:base',
@@ -30,7 +30,7 @@
'target_name': 'native_test_jni_headers',
'type': 'none',
'sources': [
- 'java/src/org/chromium/native_test/ChromeNativeTestActivity.java'
+ 'native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java'
],
'variables': {
'jni_gen_package': 'testing',
@@ -42,8 +42,8 @@
'target_name': 'native_test_util',
'type': 'static_library',
'sources': [
- 'native_test_util.cc',
- 'native_test_util.h',
+ 'native_test/native_test_util.cc',
+ 'native_test/native_test_util.h',
],
'dependencies': [
'../../base/base.gyp:base',
diff --git a/testing/android/BUILD.gn b/testing/android/native_test/BUILD.gn
similarity index 100%
rename from testing/android/BUILD.gn
rename to testing/android/native_test/BUILD.gn
diff --git a/testing/android/README.chromium b/testing/android/native_test/README.chromium
similarity index 100%
rename from testing/android/README.chromium
rename to testing/android/native_test/README.chromium
diff --git a/testing/android/java/AndroidManifest.xml b/testing/android/native_test/java/AndroidManifest.xml
similarity index 95%
rename from testing/android/java/AndroidManifest.xml
rename to testing/android/native_test/java/AndroidManifest.xml
index 8cc36b2..244f116 100644
--- a/testing/android/java/AndroidManifest.xml
+++ b/testing/android/native_test/java/AndroidManifest.xml
@@ -10,7 +10,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
similarity index 97%
rename from testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
rename to testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
index 4aafa7c..4a74877 100644
--- a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
@@ -43,7 +43,7 @@
CommandLine.init(new String[]{});
// Needed by path_utils_unittest.cc
- PathUtils.setPrivateDataDirectorySuffix("chrome");
+ PathUtils.setPrivateDataDirectorySuffix("chrome", getApplicationContext());
ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext());
resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting();
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
similarity index 100%
rename from testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
rename to testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
diff --git a/testing/android/native_test_jni_onload.cc b/testing/android/native_test/native_test_jni_onload.cc
similarity index 93%
rename from testing/android/native_test_jni_onload.cc
rename to testing/android/native_test/native_test_jni_onload.cc
index de42356..041aa74 100644
--- a/testing/android/native_test_jni_onload.cc
+++ b/testing/android/native_test/native_test_jni_onload.cc
@@ -5,7 +5,7 @@
#include "base/android/base_jni_onload.h"
#include "base/android/jni_android.h"
#include "base/bind.h"
-#include "testing/android/native_test_launcher.h"
+#include "testing/android/native_test/native_test_launcher.h"
namespace {
diff --git a/testing/android/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc
similarity index 98%
rename from testing/android/native_test_launcher.cc
rename to testing/android/native_test/native_test_launcher.cc
index 4cc87d2..51edf36 100644
--- a/testing/android/native_test_launcher.cc
+++ b/testing/android/native_test/native_test_launcher.cc
@@ -26,7 +26,7 @@
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
#include "jni/ChromeNativeTestActivity_jni.h"
-#include "testing/android/native_test_util.h"
+#include "testing/android/native_test/native_test_util.h"
using testing::native_test_util::ArgsToArgv;
using testing::native_test_util::ParseArgsFromCommandLineFile;
diff --git a/testing/android/native_test_launcher.h b/testing/android/native_test/native_test_launcher.h
similarity index 100%
rename from testing/android/native_test_launcher.h
rename to testing/android/native_test/native_test_launcher.h
diff --git a/testing/android/native_test_util.cc b/testing/android/native_test/native_test_util.cc
similarity index 95%
rename from testing/android/native_test_util.cc
rename to testing/android/native_test/native_test_util.cc
index 885f297..2eaf971 100644
--- a/testing/android/native_test_util.cc
+++ b/testing/android/native_test/native_test_util.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 "testing/android/native_test_util.h"
+#include "testing/android/native_test/native_test_util.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
diff --git a/testing/android/native_test_util.h b/testing/android/native_test/native_test_util.h
similarity index 100%
rename from testing/android/native_test_util.h
rename to testing/android/native_test/native_test_util.h
diff --git a/testing/buildbot/PRESUBMIT.py b/testing/buildbot/PRESUBMIT.py
new file mode 100644
index 0000000..a74562a
--- /dev/null
+++ b/testing/buildbot/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# 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.
+
+"""Enforces json format.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into depot_tools.
+"""
+
+
+def CommonChecks(input_api, output_api):
+ args = [input_api.python_executable, 'manage.py', '--check']
+ cmd = input_api.Command(
+ name='manage', cmd=args, kwargs={}, message=output_api.PresubmitError)
+ return input_api.RunTests([cmd])
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/testing/buildbot/chromium.chrome.json b/testing/buildbot/chromium.chrome.json
index 2c63c08..0967ef4 100644
--- a/testing/buildbot/chromium.chrome.json
+++ b/testing/buildbot/chromium.chrome.json
@@ -1,2 +1 @@
-{
-}
+{}
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 64f2cd5..e7df4ed 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1,291 +1,599 @@
{
- "Linux ChromiumOS Tests (1)": {
- "gtest_tests": [
+ "Linux ChromiumOS GN": {
+ "additional_compile_targets": [
"accessibility_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 5
- }
- },
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
"cacheinvalidation_unittests",
+ "chromedriver_unittests",
"chromeos_unittests",
+ "components_browsertests",
"components_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
"dbus_unittests",
+ "device_unittests",
"display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
"extensions_unittests",
"gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
"google_apis_unittests",
"gpu_unittests",
- "url_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "interactive_ui_tests",
+ "ipc_tests",
"jingle_unittests",
- "device_unittests",
"media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
- {
- "test": "sandbox_linux_unittests",
- "args": ["--test-launcher-print-test-stdio=always"]
- },
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
"ui_base_unittests",
"ui_chromeos_unittests",
"ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
"views_unittests",
- "wm_unittests",
- "aura_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
{
- "test": "ash_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "app_list_unittests",
- "message_center_unittests",
- "compositor_unittests",
- "events_unittests",
- "ipc_tests",
- "sync_unit_tests",
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Linux ChromiumOS GN (dbg)": {
+ "additional_compile_targets": [
+ "net_unittests"
+ ],
+ "gtest_tests": [
{
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "nacl_loader_unittests",
- "app_shell_unittests",
- "chromevox_tests",
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "skia_unittests"
+ "test": "base_unittests"
+ }
]
},
"Linux ChromiumOS Ozone Tests (1)": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "ash_unittests",
- "aura_unittests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "chromeos_unittests",
- "chromevox_tests",
- "components_unittests",
{
- "test": "content_browsertests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "chromevox_tests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "content_browsertests"
},
- "content_unittests",
{
- "test": "crypto_unittests",
+ "test": "content_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
- "events_unittests",
{
- "test": "extensions_browsertests",
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "message_center_unittests",
- "nacl_loader_unittests",
{
- "test": "net_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
- "ozone_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
{
- "test": "sandbox_linux_unittests",
- "args": ["--test-launcher-print-test-stdio=always"]
+ "test": "ozone_unittests"
},
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_chromeos_unittests",
- "ui_touch_selection_unittests",
{
- "test": "unit_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "args": [
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_chromeos_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "unit_tests"
},
- "url_unittests",
- "views_unittests",
- "wm_unittests"
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ]
+ },
+ "Linux ChromiumOS Tests (1)": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "chromevox_tests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "args": [
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_chromeos_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
]
},
"Linux ChromiumOS Tests (dbg)(1)": {
"gtest_tests": [
- "accessibility_unittests",
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
- "cacheinvalidation_unittests",
- "chromeos_unittests",
- "components_unittests",
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
- "dbus_unittests",
- "extensions_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
{
- "test": "content_unittests",
+ "test": "app_shell_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ash_unittests"
},
- "device_unittests",
- "display_unittests",
- "media_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
{
- "test": "sandbox_linux_unittests",
- "args": ["--test-launcher-print-test-stdio=always"]
+ "test": "aura_unittests"
},
- "ui_base_unittests",
- "ui_chromeos_unittests",
- "ui_touch_selection_unittests",
- "views_unittests",
- "wm_unittests",
- "aura_unittests",
{
- "test": "ash_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "app_list_unittests",
- "message_center_unittests",
- "compositor_unittests",
- "events_unittests",
- "ipc_tests",
- "sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "app_shell_unittests",
{
- "test": "content_browsertests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "extensions_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
- "gcm_unit_tests",
- "skia_unittests",
{
- "test": "interactive_ui_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "args": [
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_chromeos_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
]
}
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 8a47be4..3b3c8fe 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -1,55 +1,199 @@
{
- "Linux Trusty": {
+ "Browser Side Navigation Linux": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "aura_unittests",
- "interactive_ui_tests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "events_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "ipc_tests",
- "sync_unit_tests",
- "unit_tests",
- "views_unittests",
- "wm_unittests",
- "sql_unittests",
- "browser_tests",
- "content_browsertests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests"
+ {
+ "args": [
+ "--enable-browser-side-navigation",
+ "--gtest_filter=-BatteryMonitorImplTest.BatteryManagerDefaultValues:BatteryMonitorImplTest.BatteryManagerResolvePromise:BatteryMonitorImplTest.BatteryManagerWithEventListener:BookmarkletTest.DocumentWrite:BookmarkletTest.NonEmptyResult:BookmarkletTest.Redirect:BookmarkletTest.RedirectVoided:ChildProcessLauncherBrowserTest.ChildSpawnFail:CrossProcessFrameTreeBrowserTest.CreateCrossProcessSubframeProxies:CrossProcessFrameTreeBrowserTest.OriginSetOnCrossProcessNavigations:CrossSiteRedirectorBrowserTest.VerifyCrossSiteRedirectURL:CrossSiteTransferTest.NoLeakOnCrossSiteCancel:CrossSiteTransferTest.ReplaceEntryCrossProcessThenTransfer:CrossSiteTransferTest.ReplaceEntryCrossProcessTwice:CrossSiteTransferTest.ReplaceEntryInProcessThenTranfers:DatabaseTest.ReloadPage:DeviceInertialSensorBrowserTest.LightOneOffInfintyTest:DeviceInertialSensorBrowserTest.LightTest:DeviceInertialSensorBrowserTest.MotionNullTest:DeviceInertialSensorBrowserTest.MotionTest:DeviceInertialSensorBrowserTest.OrientationNullTest:DeviceInertialSensorBrowserTest.OrientationTest:DOMStorageBrowserTest.SanityCheck:DOMStorageBrowserTest.SanityCheckIncognito:DownloadContentTest.CancelAtFinalRename:DownloadContentTest.CancelAtRelease:DownloadContentTest.CancelInterruptedDownload:DownloadContentTest.CancelResumingDownload:DownloadContentTest.DownloadCancelled:DownloadContentTest.DownloadGZipWithNoContent:DownloadContentTest.DownloadOctetStream:DownloadContentTest.MultiDownload:DownloadContentTest.RemoveDownload:DownloadContentTest.RemoveResumingDownload:DownloadContentTest.ResumeInterruptedDownload:DownloadContentTest.ResumeInterruptedDownloadBadPrecondition:DownloadContentTest.ResumeInterruptedDownloadNoRange:DownloadContentTest.ResumeInterruptedDownloadNoVerifiers:DownloadContentTest.ResumeWithDeletedFile:DownloadContentTest.ResumeWithFileFinalRenameError:DownloadContentTest.ResumeWithFileInitError:DownloadContentTest.ResumeWithFileIntermediateRenameError:DownloadContentTest.ShutdownAtRelease:DownloadContentTest.ShutdownInProgress:File/MediaTest.VideoBearOpusOgg/0:File/MediaTest.VideoBearOpusWebm/0:File/MediaTest.VideoBearSilentTheora/0:File/MediaTest.VideoBearSilentWebm/0:File/MediaTest.VideoBearTheora/0:File/MediaTest.VideoBearWavAlaw/0:File/MediaTest.VideoBearWavMulaw/0:File/MediaTest.VideoBearWavPcm/0:File/MediaTest.VideoBearWavPcm192kHz/0:File/MediaTest.VideoBearWavPcm3kHz/0:File/MediaTest.VideoBearWebm/0:File/MediaTest.VideoTulipWebm/0:FileSystemBrowserTest.CreateTest:FileSystemBrowserTest.RequestTest:FileSystemBrowserTestWithLowQuota.QuotaTest:FrameTreeBrowserTest.FrameTreeAfterCrash:FrameTreeBrowserTest.SandboxFlagsSetForChildFrames:IndexedDBBrowserTest.BlobsCountAgainstQuota:IndexedDBBrowserTest.CallbackAccounting:IndexedDBBrowserTest.CanDeleteWhenOverQuotaTest:IndexedDBBrowserTest.ConnectionsClosedOnTabClose:IndexedDBBrowserTest.CursorPrefetch:IndexedDBBrowserTest.CursorTest:IndexedDBBrowserTest.CursorTestIncognito:IndexedDBBrowserTest.DatabaseTest:IndexedDBBrowserTest.DeleteCompactsBackingStore:IndexedDBBrowserTest.DeleteForOriginDeletesBlobs:IndexedDBBrowserTest.DiskFullOnCommit:IndexedDBBrowserTest.DoesntHangTest:IndexedDBBrowserTest.EmptyBlob:IndexedDBBrowserTest.ForceCloseEventTest:IndexedDBBrowserTest.IndexTest:IndexedDBBrowserTest.KeyPathTest:IndexedDBBrowserTest.KeyTypesTest:IndexedDBBrowserTest.LevelDBLogFileTest:IndexedDBBrowserTest.NullKeyPathPersistence:IndexedDBBrowserTest.ObjectStoreTest:IndexedDBBrowserTest.PRE_NullKeyPathPersistence:IndexedDBBrowserTest.PRE_PRE_VersionChangeCrashResilience:IndexedDBBrowserTest.PRE_VersionChangeCrashResilience:IndexedDBBrowserTest.TransactionGetTest:IndexedDBBrowserTest.TransactionTest:IndexedDBBrowserTest.VersionChangeCrashResilience:IndexedDBBrowserTestSingleProcess.RenderThreadShutdownTest:IndexedDBBrowserTestWithCorruptLevelDB.DestroyTest:IndexedDBBrowserTestWithGCExposed.BlobDidAck:IndexedDBBrowserTestWithGCExposed.BlobDidAckPrefetch:IndexedDBBrowserTestWithGCExposed.DatabaseCallbacksTest:IndexedDBBrowserTestWithLowQuota.QuotaTest:IndexedDBBrowserTestWithMissingSSTFile.DestroyTest:IndexedDBBrowserTestWithVersion0Schema.MigrationTest:IndexedDBBrowserTestWithVersion123456Schema.DestroyTest:IndexedDBBrowserTestWithVersion987654SSVData.DestroyTest:ManifestBrowserTest.DummyManifest:ManifestBrowserTest.DynamicManifest:ManifestBrowserTest.ParseErrorManifest:ManifestBrowserTest.ParsingErrorsManifest:MediaCanPlayTypeTest.CodecSupportTest_Avc1Variants:MediaCanPlayTypeTest.CodecSupportTest_Avc3Variants:MediaCanPlayTypeTest.CodecSupportTest_AvcLevels:MediaCanPlayTypeTest.CodecSupportTest_HLS:MediaCanPlayTypeTest.CodecSupportTest_mp3:MediaCanPlayTypeTest.CodecSupportTest_mp4:MediaCanPlayTypeTest.CodecSupportTest_Mp4aVariants:MediaCanPlayTypeTest.CodecSupportTest_ogg:MediaCanPlayTypeTest.CodecSupportTest_wav:MediaCanPlayTypeTest.CodecSupportTest_webm:MediaTest.Navigate:NavigationControllerBrowserTest.CorrectLengthWithCurrentItemReplacement:NavigationControllerBrowserTest.CorrectLengthWithNewTabNavigatingFromWebUI:NavigationControllerBrowserTest.DontIgnoreBackAfterNavEntryLimit:NavigationControllerBrowserTest.ErrorPageReplacement:NavigationControllerBrowserTest.NavigationTypeClassification_ClientSideRedirect:NavigationControllerBrowserTest.NavigationTypeClassification_ExistingPage:NavigationControllerBrowserTest.NavigationTypeClassification_InPage:NavigationControllerBrowserTest.NavigationTypeClassification_NewAndAutoSubframe:NavigationControllerBrowserTest.NavigationTypeClassification_NewPage:NavigationControllerBrowserTest.SubframeOnEmptyPage:OutOfProcessPPAPITest.InputEvent:OutOfProcessPPAPITest.MediaStreamAudioTrack:OutOfProcessPPAPITest.MediaStreamVideoTrack:RendererAccessibilityTest.AccessibilityMessagesQueueWhileSwappedOut:RenderFrameHostImplBrowserTest.IsFocused_AtLoad:RenderFrameHostImplBrowserTest.IsFocused_Widget:RenderFrameHostManagerTest.BackForwardNotStale:RenderFrameHostManagerTest.ClickLinkAfter204Error:RenderFrameHostManagerTest.DisownSubframeOpener:RenderFrameHostManagerTest.DontPreemptNavigationWithFrameTreeUpdate:RenderFrameHostManagerTest.ForceSwapAfterWebUIBindings:RenderFrameHostManagerTest.IgnoreRendererDebugURLsWhenCrashed:RenderFrameHostManagerTest.NoScriptAccessAfterSwapOut:RenderFrameHostManagerTest.RendererDebugURLsDontSwap:RenderFrameHostManagerTest.RestoreFileAccessForHistoryNavigation:RenderFrameHostManagerTest.RestoreSubframeFileAccessForHistoryNavigation:RenderFrameHostManagerTest.ShowLoadingURLUntilSpoof:RenderViewImplTest.DecideNavigationPolicy:RenderViewImplTest.InsertCharacters:RenderViewImplTest.NavigateFrame:RenderViewImplTest.NavigationStartOverride:RenderViewImplTest.OnHandleKeyboardEvent:RenderViewImplTest.OnNavigationHttpPost:RenderViewImplTest.ReloadWhileSwappedOut:RenderViewImplTest.StaleNavigationsIgnored:RenderViewImplTest.TestBackForward:ResourceDispatcherHostBrowserTest.CrossSiteAfterCrash:ResourceDispatcherHostBrowserTest.CrossSiteNoUnloadOn204:ResourceFetcherTests.ResourceFetcher404:ResourceFetcherTests.ResourceFetcherDeletedInCallback:ResourceFetcherTests.ResourceFetcherDidFail:ResourceFetcherTests.ResourceFetcherDownload:ResourceFetcherTests.ResourceFetcherPost:ResourceFetcherTests.ResourceFetcherSetHeader:ResourceFetcherTests.ResourceFetcherTimeout:SecurityExploitBrowserTest.AttemptDuplicateRenderViewHost:SecurityExploitBrowserTest.AttemptDuplicateRenderWidgetHost:SecurityExploitBrowserTest.InterstitialCommandFromUnderlyingContent:ServiceWorkerBrowserTest.CrossSiteTransfer:ServiceWorkerBrowserTest.ImportsBustMemcache:ServiceWorkerBrowserTest.Reload:ServiceWorkerBrowserTest.ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure:ServiceWorkerBrowserTest.ResponseFromHTTPSServiceWorkerIsMarkedAsSecure:SessionHistoryTest.BasicBackForward:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FragmentBackForward:SessionHistoryTest.FrameBackForward:SessionHistoryTest.FrameFormBackForward:SessionHistoryTest.HistoryLength:SessionHistoryTest.JavascriptHistory:SessionHistoryTest.LocationChangeInSubframe:SessionHistoryTest.LocationReplace:SitePerProcessAccessibilityBrowserTest.CrossSiteIframeAccessibility:SitePerProcessBrowserTest.CleanupCrossSiteIframe:SitePerProcessBrowserTest.CompositorFrameSwapped:SitePerProcessBrowserTest.CreateProxiesForNewFrames:SitePerProcessBrowserTest.CrossSiteDidStopLoading:SitePerProcessBrowserTest.CrossSiteIframe:SitePerProcessBrowserTest.DynamicSandboxFlags:SitePerProcessBrowserTest.DynamicSandboxFlagsRemoteToLocal:SitePerProcessBrowserTest.KillingRendererClearsDescendantProxies:SitePerProcessBrowserTest.NavigateRemoteFrame:SitePerProcessBrowserTest.NavigateRemoteFrameToBlankAndDataURLs:SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess:SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcessWithSubtree:SitePerProcessBrowserTest.NavigateWithSiblingRemoteFrame:SitePerProcessBrowserTest.OriginReplication:SitePerProcessBrowserTest.ProxyCreationSkipsSubtree:SitePerProcessBrowserTest.RFPHDestruction:SitePerProcessBrowserTest.RestrictFrameDetach:SitePerProcessBrowserTest.SandboxFlagsReplication:SitePerProcessBrowserTest.SubframePostMessage:SitePerProcessDevToolsBrowserTest.CrossSiteIframeAgentHost:SpeechRecognitionBrowserTest.OneShotRecognition:StatsTableBrowserTest.StartWithStatTable:TransitionBrowserTest.NormalNavigationNotDeferred:TransitionBrowserTest.TransitionNavigationDataIsCleared:TransitionBrowserTest.TransitionNavigationIsDeferred:WebContentsImplBrowserTest.ClearNonVisiblePendingOnFail:WebContentsImplBrowserTest.GetSizeForNewRenderView:WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews:WebUIMojoTest.EndToEndPing:WorkerTest.IncognitoSharedWorkers:WorkerTest.MultipleSharedWorkers:WorkerTest.MultipleWorkers:WorkerTest.PassMessagePortToSharedWorker:WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect:WorkerTest.SharedWorkerTlsClientAuth:WorkerTest.SingleSharedWorker:WorkerTest.SingleWorker:WorkerTest.WorkerTlsClientAuth"
+ ],
+ "test": "content_browsertests"
+ },
+ {
+ "args": [
+ "--enable-browser-side-navigation",
+ "--gtest_filter=-NavigationControllerTest.CopyRestoredStateAndNavigate:NavigationControllerTest.LoadURL_AbortDoesntCancelPending:NavigationControllerTest.LoadURL_IgnorePreemptsPending:NavigationControllerTest.ShowRendererURLAfterFailUntilModified:NavigationControllerTest.ShowRendererURLInNewTabUntilModified:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:RenderFrameHostManagerTest.NavigateWithEarlyClose:RenderFrameHostManagerTest.PageDoesBackAndReload:RenderViewHostTest.ResetUnloadOnReload:ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:WebContentsImplTest.ActiveContentsCountChangeBrowsingInstance:WebContentsImplTest.CrossSiteNavigationBackPreempted:WebContentsImplTest.CrossSiteNavigationPreempted:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload:WebContentsImplTest.NoEarlyStop:WebContentsImplTest.ShowInterstitialCrashRendererThenGoBack:WebContentsImplTest.ShowInterstitialFromBrowserNewNavigationProceed:WebContentsImplTest.ShowInterstitialThenGoBack"
+ ],
+ "test": "content_unittests"
+ }
+ ]
+ },
+ "Cast Linux": {
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_base_unittests"
+ },
+ {
+ "test": "cast_media_unittests"
+ },
+ {
+ "test": "cast_shell_browser_test"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "url_unittests"
+ }
+ ]
+ },
+ "Chromium Mac 10.10": {
+ "gtest_tests": [
+ {
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
],
"scripts": [
{
@@ -66,57 +210,1845 @@
}
]
},
- "Linux Trusty (dbg)": {
+ "ClangToTLinux tester": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "aura_unittests",
- "interactive_ui_tests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "events_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "ipc_tests",
- "sync_unit_tests",
- "unit_tests",
- "views_unittests",
- "wm_unittests",
- "sql_unittests",
- "browser_tests",
- "content_browsertests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
+ ]
+ },
+ "ClangToTLinuxASan tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 4
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
+ ]
+ },
+ "ClangToTMac tester": {
+ "gtest_tests": [
+ {
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "telemetry_unittests",
+ "script": "telemetry_unittests.py"
+ },
+ {
+ "name": "telemetry_perf_unittests",
+ "script": "telemetry_perf_unittests.py"
+ },
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
+ ]
+ },
+ "ClangToTMacASan tester": {
+ "gtest_tests": [
+ {
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "telemetry_unittests",
+ "script": "telemetry_unittests.py"
+ },
+ {
+ "name": "telemetry_perf_unittests",
+ "script": "telemetry_perf_unittests.py"
+ },
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
+ ]
+ },
+ "CrWinAsan tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinAsan(dll) tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang(dbg) tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang(shared) tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang64 tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang64(dbg) tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClang64(dll) tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "CrWinClangLLD tester": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "Linux ARM Cross-Compile": {
+ "compile_targets": [
+ "browser_tests_run"
+ ],
+ "gtest_tests": [
+ {
+ "test": "browser_tests"
+ }
+ ]
+ },
+ "Linux Trusty": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -135,55 +2067,324 @@
},
"Linux Trusty (32)": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "aura_unittests",
- "interactive_ui_tests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "events_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "ipc_tests",
- "sync_unit_tests",
- "unit_tests",
- "views_unittests",
- "wm_unittests",
- "sql_unittests",
- "browser_tests",
- "content_browsertests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests"
+ {
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "telemetry_unittests",
+ "script": "telemetry_unittests.py"
+ },
+ {
+ "name": "telemetry_perf_unittests",
+ "script": "telemetry_perf_unittests.py"
+ },
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
+ ]
+ },
+ "Linux Trusty (dbg)": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -202,121 +2403,153 @@
},
"Linux Trusty (dbg)(32)": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "aura_unittests",
- "interactive_ui_tests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "events_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "ipc_tests",
- "sync_unit_tests",
- "unit_tests",
- "views_unittests",
- "wm_unittests",
- "sql_unittests",
- "browser_tests",
- "content_browsertests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests"
- ],
- "scripts": [
{
- "name": "telemetry_unittests",
- "script": "telemetry_unittests.py"
+ "test": "accessibility_unittests"
},
{
- "name": "telemetry_perf_unittests",
- "script": "telemetry_perf_unittests.py"
+ "test": "app_list_unittests"
},
{
- "name": "nacl_integration",
- "script": "nacl_integration.py"
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
- ]
- },
- "Linux ARM Cross-Compile": {
- "compile_targets": [
- "browser_tests_run"
- ],
- "gtest_tests": [
- "browser_tests"
- ]
- },
- "Chromium Mac 10.10": {
- "gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "content_browsertests",
- "content_unittests",
- "crypto_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "gpu_unittests",
- "google_apis_unittests",
- "interactive_ui_tests",
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "message_center_unittests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_mac_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_integration_tests",
- "sync_unit_tests",
- "ui_base_unittests",
- "unit_tests",
- "url_unittests",
- "browser_tests"
],
"scripts": [
{
@@ -335,818 +2568,62 @@
},
"Site Isolation Linux": {
"gtest_tests": [
- { "test": "content_unittests", "args": ["--site-per-process"] },
- { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
- { "test": "unit_tests", "args": ["--site-per-process"] },
- { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
+ {
+ "args": [
+ "--site-per-process",
+ "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*"
+ ],
+ "test": "browser_tests"
+ },
+ {
+ "args": [
+ "--site-per-process",
+ "--gtest_filter=-*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"
+ ],
+ "test": "content_browsertests"
+ },
+ {
+ "args": [
+ "--site-per-process"
+ ],
+ "test": "content_unittests"
+ },
+ {
+ "args": [
+ "--site-per-process"
+ ],
+ "test": "unit_tests"
+ }
]
},
"Site Isolation Win": {
"gtest_tests": [
- { "test": "content_unittests", "args": ["--site-per-process"] },
- { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
- { "test": "unit_tests", "args": ["--site-per-process"] },
- { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
- ]
- },
- "Browser Side Navigation Linux": {
- "gtest_tests": [
- { "test": "content_unittests", "args": ["--enable-browser-side-navigation", "--gtest_filter=-ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload"] },
- { "test": "content_browsertests", "args": ["--enable-browser-side-navigation"] }
- ]
- },
- "CrWinClang tester": {
- "gtest_tests": [
{
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "args": [
+ "--site-per-process",
+ "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*"
+ ],
+ "test": "browser_tests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
+ "args": [
+ "--site-per-process",
+ "--gtest_filter=-*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"
+ ],
+ "test": "content_browsertests"
},
{
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClang(dbg) tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "args": [
+ "--site-per-process"
+ ],
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClang(shared) tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClang64 tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClang64(dbg) tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClang64(dll) tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinClangLLD tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- "unit_tests",
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- "browser_tests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinAsan tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- "unit_tests",
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- "browser_tests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "CrWinAsan(dll) tester": {
- "gtest_tests": [
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chrome_elf_unittests",
- "components_unittests",
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "ipc_tests",
- "sync_unit_tests",
- "skia_unittests",
- "unit_tests",
- "sql_unittests",
- "ui_base_unittests",
- "views_unittests",
- "browser_tests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests"
- ]
- },
- "ClangToTLinux tester": {
- "gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- "aura_unittests",
- "interactive_ui_tests",
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "events_unittests",
- "media_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "ipc_tests",
- "sync_unit_tests",
- "unit_tests",
- "views_unittests",
- "wm_unittests",
- "sql_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "content_browsertests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests"
- ],
- "scripts": [
- {
- "name": "nacl_integration",
- "script": "nacl_integration.py"
+ "args": [
+ "--site-per-process"
+ ],
+ "test": "unit_tests"
}
]
- },
- "ClangToTLinuxASan tester": {
- "gtest_tests": [
- "accessibility_unittests",
- "extensions_browsertests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 5
- }
- },
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "components_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 4
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- "url_unittests"
- ]
- },
- "Cast Linux": {
- "gtest_tests": [
- "base_unittests",
- "cacheinvalidation_unittests",
- "cast_media_unittests",
- "cast_shell_browser_test",
- "content_unittests",
- "crypto_unittests",
- "gpu_unittests",
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "net_unittests",
- "sandbox_linux_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "url_unittests"
- ]
}
}
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 48ed324..88acb35 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1,123 +1,142 @@
{
- "Linux Tests": {
+ "Android GN": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "Android Tests": {
+ "scripts": [
+ {
+ "name": "webview_licenses",
+ "script": "webview_licenses.py"
+ }
+ ]
+ },
+ "Android Tests (dbg)": {
+ "scripts": [
+ {
+ "name": "webview_licenses",
+ "script": "webview_licenses.py"
+ }
+ ]
+ },
+ "Linux Clang (dbg)": {
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_list_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "app_shell_unittests"
},
- "app_shell_unittests",
+ {
+ "test": "base_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gn_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ }
+ ]
+ },
+ "Linux GN": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
"aura_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 5
- }
- },
+ "browser_tests",
"cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "cast_unittests",
+ "cc_unittests",
"chromedriver_unittests",
- {
- "test": "components_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "compositor_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
"dbus_unittests",
"device_unittests",
"display_unittests",
- {
- "test": "events_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "events_unittests",
+ "extensions_browsertests",
"extensions_unittests",
"gcm_unit_tests",
- {
- "test": "gfx_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "gfx_unittests",
+ "gn_unittests",
"google_apis_unittests",
- {
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "gpu_unittests",
+ "interactive_ui_tests",
"ipc_mojo_unittests",
"ipc_tests",
"jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "media_unittests",
"mojo_common_unittests",
"mojo_public_bindings_unittests",
"mojo_public_environment_unittests",
@@ -125,46 +144,318 @@
"mojo_public_utility_unittests",
"mojo_system_unittests",
"nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "net_unittests",
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
"sandbox_linux_unittests",
+ "skia_unittests",
"sql_unittests",
- {
- "test": "ui_base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "ui_touch_selection_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "sync_integration_tests",
"sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
"url_unittests",
"views_unittests",
- "wm_unittests",
- "skia_unittests"
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Linux GN (dbg)": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Linux Tests": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cast_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "gn_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -193,338 +484,235 @@
}
]
},
- "Linux Tests (dbg)(1)(32)": {
- "gtest_tests": [
- {
- "test": "accessibility_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "app_list_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "app_shell_unittests",
- "aura_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- "cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "chromedriver_unittests",
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "compositor_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
- {
- "test": "events_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- {
- "test": "gfx_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "google_apis_unittests",
- {
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "sql_unittests",
- {
- "test": "ui_base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "ui_touch_selection_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
- ],
- "scripts": [
- {
- "name": "nacl_integration",
- "script": "nacl_integration.py"
- }
- ]
- },
"Linux Tests (dbg)(1)": {
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_list_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
- "app_shell_unittests",
- "aura_unittests",
{
- "test": "base_unittests",
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
{
- "test": "cast_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
- "chromedriver_unittests",
{
- "test": "components_unittests",
+ "test": "chromedriver_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
- "compositor_unittests",
{
- "test": "content_browsertests",
+ "test": "compositor_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
{
- "test": "events_unittests",
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "events_unittests"
},
{
- "test": "extensions_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
- "extensions_unittests",
- "gcm_unit_tests",
{
- "test": "gfx_unittests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gfx_unittests"
},
- "google_apis_unittests",
{
- "test": "gpu_unittests",
+ "test": "gn_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
{
- "test": "media_unittests",
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
{
- "test": "net_unittests",
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
{
- "test": "sandbox_linux_unittests",
- "args": ["--test-launcher-print-test-stdio=always"]
+ "test": "ppapi_unittests"
},
- "sql_unittests",
{
- "test": "ui_base_unittests",
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "args": [
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "sync_integration_tests"
},
{
- "test": "ui_touch_selection_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "sync_unit_tests"
},
{
- "test": "sync_integration_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ui_base_unittests"
},
- "sync_unit_tests",
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ui_touch_selection_unittests"
},
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -541,48 +729,236 @@
}
]
},
- "Linux Clang (dbg)": {
+ "Linux Tests (dbg)(1)(32)": {
"gtest_tests": [
- "accessibility_unittests",
- "app_shell_unittests",
- "base_unittests",
- "components_unittests",
- "content_unittests",
- "crypto_unittests",
- "device_unittests",
- "display_unittests",
- "extensions_unittests",
- "google_apis_unittests",
- "ipc_mojo_unittests",
- "ipc_tests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- "sandbox_linux_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "unit_tests",
- "skia_unittests"
- ]
- },
- "Android Tests (dbg)": {
- "scripts": [
{
- "name": "check_licenses",
- "script": "webview_licenses.py"
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cast_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "gn_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
- ]
- },
- "Android Tests": {
+ ],
"scripts": [
{
- "name": "check_licenses",
- "script": "webview_licenses.py"
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
}
]
}
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index a5de375..8883601 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -1,149 +1,263 @@
{
- "Mac10.6 Tests": {
- "gtest_tests": [
- {
- "test": "accessibility_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "app_list_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
+ "Mac GN": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "base_unittests",
"cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "cast_unittests",
+ "cc_unittests",
"chromedriver_unittests",
- {
- "test": "components_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
+ "crypto_unittests",
"gcm_unit_tests",
- {
- "test": "gfx_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "google_apis_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "gn_unittests",
+ "gpu_unittests",
"ipc_tests",
"jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "message_center_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "media_unittests",
"mojo_common_unittests",
"mojo_public_bindings_unittests",
"mojo_public_environment_unittests",
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
"ppapi_unittests",
"printing_unittests",
- "remoting_unittests",
- "sandbox_mac_unittests",
+ "skia_unittests",
"sql_unittests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
"sync_unit_tests",
+ "ui_base_unittests",
+ "url_unittests"
+ ],
+ "gtest_tests": [
{
- "test": "ui_base_unittests",
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Mac GN (dbg)": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "base_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "crypto_unittests",
+ "gcm_unit_tests",
+ "gn_unittests",
+ "gpu_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "url_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Mac10.6 Tests": {
+ "gtest_tests": [
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
- "url_unittests",
- "skia_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cast_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
],
"scripts": [
{
@@ -163,142 +277,186 @@
"Mac10.8 Tests": {
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_list_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
- },
- "cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "browser_tests"
},
{
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "chromedriver_unittests",
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "cacheinvalidation_unittests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- {
- "test": "gfx_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "chromedriver_unittests"
},
{
- "test": "gpu_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "google_apis_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ipc_tests",
- "jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "message_center_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_mac_unittests",
- "sql_unittests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sync_unit_tests",
- {
- "test": "ui_base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
- "url_unittests",
- "skia_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
],
"scripts": [
{
@@ -318,142 +476,186 @@
"Mac10.9 Tests": {
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_list_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
- },
- "cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "browser_tests"
},
{
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "chromedriver_unittests",
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "cacheinvalidation_unittests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- {
- "test": "gfx_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "chromedriver_unittests"
},
{
- "test": "gpu_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "google_apis_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ipc_tests",
- "jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "message_center_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_mac_unittests",
- "sql_unittests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sync_unit_tests",
- {
- "test": "ui_base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
- "url_unittests",
- "skia_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
],
"scripts": [
{
@@ -473,143 +675,187 @@
"Mac10.9 Tests (dbg)": {
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_list_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
{
- "test": "cast_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
- "chromedriver_unittests",
{
- "test": "components_unittests",
+ "test": "chromedriver_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "extensions_unittests",
- "gcm_unit_tests",
{
- "test": "gfx_unittests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gfx_unittests"
},
{
- "test": "gpu_unittests",
+ "test": "google_apis_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
- "google_apis_unittests",
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
- },
- "ipc_tests",
- "jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "interactive_ui_tests"
},
{
- "test": "message_center_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_mac_unittests",
- "sql_unittests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sync_unit_tests",
- {
- "test": "ui_base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "ipc_tests"
},
{
- "test": "unit_tests",
+ "test": "jingle_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
- "url_unittests",
- "skia_unittests"
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_mac_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ }
],
"scripts": [
{
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 644bd9e..dc1a9d7 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -1,209 +1,484 @@
{
- "Linux MSan Tests": {
- "gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "aura_unittests",
- "base_unittests",
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 5
- }
- },
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "content_browsertests",
- "content_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
- "events_unittests",
- "extensions_browsertests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "unit_tests",
- "url_unittests",
- "views_unittests",
- "wm_unittests"
- ]
- },
"Linux ChromeOS MSan Tests": {
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "aura_unittests",
- "base_unittests",
{
- "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 5
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- "compositor_unittests",
- "content_browsertests",
- "content_unittests",
- "crypto_unittests",
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
- "events_unittests",
- "extensions_browsertests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- "net_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "unit_tests",
- "url_unittests",
- "views_unittests",
- "wm_unittests"
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ]
+ },
+ "Linux MSan Tests": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
]
},
"Linux TSan Tests": {
+ "disabled_tests": {
+ "app_shell_browsertests": "http://crbug.com/455633",
+ "browser_tests": "Too many errors, clean content_browsertests first. http://crbug.com/368525",
+ "cc_unittests": "http://crbug.com/437454",
+ "interactive_ui_tests": "http://crbug.com/455679"
+ },
"gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- "aura_unittests",
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
- "cacheinvalidation_unittests",
- "cast_unittests",
- "chromedriver_unittests",
- "components_unittests",
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "content_unittests",
+ "test": "aura_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
- "crypto_unittests",
- "dbus_unittests",
- "device_unittests",
- "display_unittests",
- "events_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "mojo_common_unittests",
{
- "test": "net_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 4
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
{
- "test": "unit_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "unit_tests"
},
- "url_unittests",
- "views_unittests",
- "wm_unittests"
- ],
- "disabled_tests": {
- "app_shell_browsertests": "http://crbug.com/455633",
- "cc_unittests": "http://crbug.com/437454",
- "browser_tests":
- "Too many errors, clean content_browsertests first. http://crbug.com/368525",
- "interactive_ui_tests": "http://crbug.com/455679"
- }
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ]
}
}
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 87a67e4..dcdfe7c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -1,335 +1,527 @@
{
"Linux ASan LSan Tests (1)": {
"gtest_tests": [
- "accessibility_unittests",
- "extensions_browsertests",
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
- "shards": 5
- }
+ "shards": 10
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
- "cast_unittests",
- "cc_unittests",
- "components_unittests",
{
- "test": "content_browsertests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "device_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- "gpu_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
"swarming": {
- "can_use_on_swarming_builders": true
- }
+ "can_use_on_swarming_builders": true,
+ "shards": 3
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
{
- "test": "net_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 4
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
{
- "test": "unit_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "unit_tests"
},
- "url_unittests"
+ {
+ "test": "url_unittests"
+ }
]
},
"Linux ASan Tests (sandboxed)": {
"gtest_tests": [
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 5
- }
+ },
+ "test": "browser_tests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "interactive_ui_tests"
+ }
+ ]
+ },
+ "Linux Chromium OS ASan LSan Tests (1)": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cast_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 4
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_chromeos_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ }
+ ]
+ },
+ "Mac ASan 64 Tests (1)": {
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 20
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
}
]
},
"Mac ASan Tests (1)": {
"gtest_tests": [
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
{
- "test": "content_browsertests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "gcm_unit_tests",
- "gpu_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
{
- "test": "net_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "url_unittests"
- ]
- },
- "Mac ASan 64 Tests (1)": {
- "gtest_tests": [
- "base_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
{
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 20
- }
- },
- "cacheinvalidation_unittests",
- "cc_unittests",
- "chromedriver_unittests",
- "components_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
+ "test": "ppapi_unittests"
},
{
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "printing_unittests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "gcm_unit_tests",
- "gpu_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "url_unittests"
- ]
- },
- "Linux Chromium OS ASan LSan Tests (1)": {
- "gtest_tests": [
- "accessibility_unittests",
- "app_list_unittests",
- {
- "test": "ash_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "aura_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "remoting_unittests"
},
{
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- "cacheinvalidation_unittests",
- "cast_unittests",
- "chromeos_unittests",
- "compositor_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "sql_unittests"
},
{
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "sync_unit_tests"
},
- "components_unittests",
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "ui_base_unittests"
},
- "device_unittests",
- "display_unittests",
- "events_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "gpu_unittests",
- "google_apis_unittests",
{
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- "ipc_tests",
- "jingle_unittests",
- "media_unittests",
- "message_center_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 4
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "skia_unittests",
- "sql_unittests",
- "sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- "ui_base_unittests",
- "ui_chromeos_unittests",
- "ui_touch_selection_unittests",
- "url_unittests",
- "views_unittests"
+ "test": "url_unittests"
+ }
]
}
}
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index ec70b5b..f3ad4ca 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1,87 +1,23 @@
{
- "Linux Perf (3)": {
- "scripts": [
- {
- "name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
- }
- ]
- },
- "Android Nexus4 Perf": {
+ "Android MotoE Perf": {
"scripts": [
{
"name": "host_info",
"script": "host_info.py"
},
{
+ "args": [
+ "gpu_perftests"
+ ],
"name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
+ "script": "gtest_perf_test.py"
},
{
+ "args": [
+ "cc_perftests"
+ ],
"name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
- }
- ]
- },
- "Android Nexus5 Perf": {
- "scripts": [
- {
- "name": "host_info",
- "script": "host_info.py"
- },
- {
- "name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
- },
- {
- "name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
- }
- ]
- },
- "Android Nexus6 Perf": {
- "scripts": [
- {
- "name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
- }
- ]
- },
- "Android Nexus7v2 Perf": {
- "scripts": [
- {
- "name": "host_info",
- "script": "host_info.py"
- },
- {
- "name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
- },
- {
- "name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
- }
- ]
- },
- "Android Nexus9 Perf": {
- "scripts": [
- {
- "name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
- },
- {
- "name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
+ "script": "gtest_perf_test.py"
}
]
},
@@ -92,72 +28,326 @@
"script": "host_info.py"
},
{
+ "args": [
+ "gpu_perftests"
+ ],
"name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
+ "script": "gtest_perf_test.py"
},
{
+ "args": [
+ "cc_perftests"
+ ],
"name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
+ "script": "gtest_perf_test.py"
}
]
},
- "Android One Perf": {
- "scripts": [
- ]
- },
- "Android MotoE Perf": {
+ "Android Nexus4 Perf": {
"scripts": [
{
"name": "host_info",
"script": "host_info.py"
},
{
+ "args": [
+ "gpu_perftests"
+ ],
"name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests"]
+ "script": "gtest_perf_test.py"
},
{
+ "args": [
+ "cc_perftests"
+ ],
"name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests"]
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Android Nexus5 Perf": {
+ "scripts": [
+ {
+ "name": "host_info",
+ "script": "host_info.py"
+ },
+ {
+ "args": [
+ "gpu_perftests"
+ ],
+ "name": "gpu_perftests",
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "cc_perftests"
+ ],
+ "name": "cc_perftests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Android Nexus6 Perf": {
+ "scripts": [
+ {
+ "name": "host_info",
+ "script": "host_info.py"
+ },
+ {
+ "args": [
+ "cc_perftests"
+ ],
+ "name": "cc_perftests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Android Nexus7v2 Perf": {
+ "scripts": [
+ {
+ "name": "host_info",
+ "script": "host_info.py"
+ },
+ {
+ "args": [
+ "gpu_perftests"
+ ],
+ "name": "gpu_perftests",
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "cc_perftests"
+ ],
+ "name": "cc_perftests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Android Nexus9 Perf": {
+ "scripts": [
+ {
+ "name": "host_info",
+ "script": "host_info.py"
+ },
+ {
+ "args": [
+ "gpu_perftests"
+ ],
+ "name": "gpu_perftests",
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "cc_perftests"
+ ],
+ "name": "cc_perftests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Android One Perf": {
+ "scripts": [
+ {
+ "name": "host_info",
+ "script": "host_info.py"
+ }
+ ]
+ },
+ "Linux Perf (3)": {
+ "scripts": [
+ {
+ "args": [
+ "cc_perftests",
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "name": "cc_perftests",
+ "script": "gtest_perf_test.py"
}
]
},
"Mac 10.8 Perf (1)": {
"scripts": [
{
- "name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+ "args": [
+ "gpu_perftests",
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "name": "gpu_perftests",
+ "script": "gtest_perf_test.py"
}
]
},
"Mac 10.8 Perf (3)": {
"scripts": [
{
+ "args": [
+ "cc_perftests",
+ "--test-launcher-print-test-stdio=always"
+ ],
"name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
}
]
},
"Mac 10.9 Perf (1)": {
"scripts": [
{
- "name": "gpu_perftests",
- "script": "gtest_perf_test.py",
- "args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+ "args": [
+ "gpu_perftests",
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "name": "gpu_perftests",
+ "script": "gtest_perf_test.py"
}
]
},
"Mac 10.9 Perf (3)": {
"scripts": [
{
+ "args": [
+ "cc_perftests",
+ "--test-launcher-print-test-stdio=always"
+ ],
"name": "cc_perftests",
- "script": "gtest_perf_test.py",
- "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 ATI GPU Perf": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 Intel GPU Perf": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 Low-End Perf (2)": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 Nvidia GPU Perf": {
+ "scripts": [
+ {
+ "args": [
+ "angle_perftests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=DrawCallPerf*",
+ "--test-launcher-jobs=1"
+ ],
+ "name": "angle_perftests",
+ "script": "gtest_perf_test.py"
+ },
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 Perf (3)": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 7 x64 Perf (2)": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
+ }
+ ]
+ },
+ "Win 8 Perf (2)": {
+ "scripts": [
+ {
+ "args": [
+ "performance_browser_tests",
+ "--test-launcher-print-test-stdio=always",
+ "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+ "--test-launcher-jobs=1",
+ "--enable-gpu"
+ ],
+ "name": "performance_browser_tests",
+ "script": "gtest_perf_test.py"
}
]
}
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index 9933e3b..5742add 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -1,208 +1,506 @@
{
- "WebKit XP": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
+ "Android GN": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
],
- "scripts": [
+ "gtest_tests": []
+ },
+ "Android GN (dbg)": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "Linux ChromiumOS Tests (1)": {
+ "gtest_tests": [
{
- "name": "webkit_lint",
- "script": "webkit_lint.py"
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
},
{
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "chromevox_tests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
]
},
- "WebKit Win7": {
+ "Linux ChromiumOS Tests (2)": {
+ "gtest_tests": []
+ },
+ "Linux ChromiumOS Tests (dbg)(1)": {
"gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
{
- "name": "webkit_lint",
- "script": "webkit_lint.py"
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
},
{
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 20
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "test": "chromeos_unittests"
+ },
+ {
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "dbus_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "display_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "test": "gpu_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 3
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sandbox_linux_unittests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
]
},
- "WebKit Win7 (dbg)": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
+ "Linux ChromiumOS Tests (dbg)(2)": {
+ "gtest_tests": []
+ },
+ "Linux ChromiumOS Tests (dbg)(3)": {
+ "gtest_tests": []
+ },
+ "Linux GN": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "nacl_loader_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
],
- "scripts": [
+ "gtest_tests": [
{
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
+ "test": "base_unittests"
}
]
},
- "WebKit Mac10.6": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
+ "Linux GN (dbg)": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.7": {
"gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
{
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.8": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.8 (retina)": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.9": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.6 (dbg)": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
- }
- ]
- },
- "WebKit Mac10.7 (dbg)": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
- {
- "name": "webkit_lint",
- "script": "webkit_lint.py"
- },
- {
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
+ "test": "base_unittests"
}
]
},
"WebKit Linux": {
"gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
- ],
- "scripts": [
{
- "name": "webkit_lint",
- "script": "webkit_lint.py"
+ "test": "blink_heap_unittests"
},
{
- "name": "webkit_python_tests",
- "script": "webkit_python_tests.py"
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
}
- ]
- },
- "WebKit Linux 32": {
- "gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
],
"scripts": [
{
@@ -217,10 +515,18 @@
},
"WebKit Linux (dbg)": {
"gtest_tests": [
- "blink_heap_unittests",
- "blink_platform_unittests",
- "webkit_unit_tests",
- "wtf_unittests"
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
],
"scripts": [
{
@@ -233,216 +539,498 @@
}
]
},
- "Linux ChromiumOS Tests (1)": {
+ "WebKit Linux 32": {
"gtest_tests": [
- "accessibility_unittests",
{
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "blink_heap_unittests"
},
{
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 5
- }
- },
- "cacheinvalidation_unittests",
- "chromeos_unittests",
- "components_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "blink_platform_unittests"
},
{
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "webkit_unit_tests"
},
{
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "dbus_unittests",
- "display_unittests",
- "extensions_unittests",
- "gcm_unit_tests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
{
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "jingle_unittests",
- "content_unittests",
- "device_unittests",
- "media_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "views_unittests",
- "wm_unittests",
- "aura_unittests",
- {
- "test": "ash_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "app_list_unittests",
- "message_center_unittests",
- "compositor_unittests",
- "events_unittests",
- "ipc_tests",
- "sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "nacl_loader_unittests",
- "app_shell_unittests",
- "chromevox_tests",
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "skia_unittests"
- ]
- },
- "Linux ChromiumOS Tests (2)": {
- "gtest_tests": [
- ]
- },
- "Linux ChromiumOS Tests (dbg)(1)": {
- "gtest_tests": [
- "accessibility_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "cacheinvalidation_unittests",
- "chromeos_unittests",
- "components_unittests",
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "dbus_unittests",
- "extensions_unittests",
- "google_apis_unittests",
- "gpu_unittests",
- "url_unittests",
- "jingle_unittests",
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "display_unittests",
- "media_unittests",
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sandbox_linux_unittests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "views_unittests",
- "wm_unittests",
- "aura_unittests",
- {
- "test": "ash_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "app_list_unittests",
- "message_center_unittests",
- "compositor_unittests",
- "events_unittests",
- "ipc_tests",
- "sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
},
{
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 20
- }
- },
- "app_shell_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "gcm_unit_tests",
- "skia_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 3
- }
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
}
]
},
- "Linux ChromiumOS Tests (dbg)(2)": {
+ "WebKit Linux Leak": {
"gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
]
},
- "Linux ChromiumOS Tests (dbg)(3)": {
+ "WebKit Linux Oilpan": {
"gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Linux Oilpan (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Linux Oilpan Leak": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac Oilpan": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac Oilpan (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.6": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.6 (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.7": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.7 (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.8": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.8 (retina)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Mac10.9": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Win Oilpan": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Win Oilpan (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Win7": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit Win7 (dbg)": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
+ ]
+ },
+ "WebKit XP": {
+ "gtest_tests": [
+ {
+ "test": "blink_heap_unittests"
+ },
+ {
+ "test": "blink_platform_unittests"
+ },
+ {
+ "test": "webkit_unit_tests"
+ },
+ {
+ "test": "wtf_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "webkit_lint",
+ "script": "webkit_lint.py"
+ },
+ {
+ "name": "webkit_python_tests",
+ "script": "webkit_python_tests.py"
+ }
]
}
}
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 3f69a8e..ca0ab23 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -1,141 +1,456 @@
{
- "XP Tests (1)": {
+ "Vista Tests (1)": {
"gtest_tests": [
- "accessibility_unittests",
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
- "app_shell_unittests",
- "aura_unittests",
{
- "test": "browser_tests",
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
{
- "test": "cast_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
- "chromedriver_unittests",
- "chrome_elf_unittests",
{
- "test": "components_browsertests",
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "components_unittests",
+ "test": "compositor_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
- "compositor_unittests",
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "courgette_unittests"
},
{
- "test": "courgette_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
{
- "test": "crypto_unittests",
+ "test": "events_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
- "events_unittests",
{
- "test": "extensions_browsertests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
{
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
+ "test": "installer_util_unittests"
},
- "installer_util_unittests",
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_mojo_unittests",
- "ipc_tests",
- "jingle_unittests",
{
- "test": "media_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
- "nacl_loader_unittests",
{
- "test": "net_unittests",
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "sql_unittests",
{
- "test": "sync_integration_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "sync_integration_tests"
},
- "sync_unit_tests",
{
- "test": "unit_tests",
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "unit_tests"
},
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ],
+ "scripts": []
+ },
+ "Win 7 Tests x64 (1)": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_installer_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "app_list_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cast_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "device_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "keyboard_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -152,466 +467,368 @@
}
]
},
- "Vista Tests (1)": {
- "gtest_tests": [
+ "Win x64 GN": {
+ "additional_compile_targets": [
"accessibility_unittests",
+ "app_list_unittests",
"app_shell_unittests",
+ "ash_unittests",
"aura_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
"cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "chromedriver_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
"chrome_elf_unittests",
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
"compositor_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
"events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
"gcm_unit_tests",
"gfx_unittests",
"google_apis_unittests",
- {
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
"ipc_tests",
"jingle_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
"mojo_common_unittests",
"mojo_public_bindings_unittests",
"mojo_public_environment_unittests",
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
"ppapi_unittests",
"printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
"sbox_integration_tests",
+ "sbox_unittests",
"sbox_validation_tests",
+ "skia_unittests",
"sql_unittests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
+ "sync_integration_tests",
"sync_unit_tests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
"ui_base_unittests",
"ui_touch_selection_unittests",
"url_unittests",
"views_unittests",
- "wm_unittests",
- "skia_unittests"
+ "wm_unittests"
],
- "scripts": [
+ "gtest_tests": [
{
- "name": "telemetry_unittests",
- "script": "telemetry_unittests.py"
- },
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Win x64 GN (dbg)": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
{
- "name": "telemetry_perf_unittests",
- "script": "telemetry_perf_unittests.py"
+ "test": "base_unittests"
}
]
},
"Win7 Tests (1)": {
"gtest_tests": [
- "app_installer_unittests",
- "app_list_unittests",
- "accessibility_unittests",
{
- "test": "ash_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
- "app_shell_unittests",
- "aura_unittests",
{
- "test": "base_unittests",
+ "test": "app_installer_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "browser_tests",
+ "test": "app_shell_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
{
- "test": "cast_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
- "chromedriver_unittests",
- "chrome_elf_unittests",
- "components_browsertests",
{
- "test": "components_unittests",
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "test": "components_browsertests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
- "compositor_unittests",
{
- "test": "content_browsertests",
+ "test": "compositor_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "courgette_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "courgette_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "device_unittests",
- "events_unittests",
{
- "test": "extensions_browsertests",
+ "test": "device_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
{
- "test": "gpu_unittests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
- "installer_util_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "installer_util_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_tests",
- "jingle_unittests",
- "keyboard_unittests",
{
- "test": "media_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "test": "keyboard_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
- "message_center_unittests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
{
- "test": "net_unittests",
+ "test": "message_center_unittests"
+ },
+ {
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "sql_unittests",
{
- "test": "sync_integration_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "sync_integration_tests"
},
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
{
- "test": "unit_tests",
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
- },
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
- ],
- "scripts": [
- {
- "name": "telemetry_unittests",
- "script": "telemetry_unittests.py"
+ },
+ "test": "unit_tests"
},
{
- "name": "telemetry_perf_unittests",
- "script": "telemetry_perf_unittests.py"
+ "test": "url_unittests"
},
{
- "name": "nacl_integration",
- "script": "nacl_integration.py"
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
}
- ]
- },
- "Win 7 Tests x64 (1)": {
- "gtest_tests": [
- "accessibility_unittests",
- {
- "test": "base_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "browser_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 10
- }
- },
- "app_installer_unittests",
- "app_list_unittests",
- "app_shell_unittests",
- {
- "test": "ash_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "aura_unittests",
- "cacheinvalidation_unittests",
- {
- "test": "cast_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "cc_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "chromedriver_unittests",
- "chrome_elf_unittests",
- "components_browsertests",
- {
- "test": "components_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "compositor_unittests",
- {
- "test": "content_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "content_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "courgette_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- {
- "test": "crypto_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "device_unittests",
- "events_unittests",
- {
- "test": "extensions_browsertests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "extensions_unittests",
- "gcm_unit_tests",
- "gfx_unittests",
- "google_apis_unittests",
- {
- "test": "gpu_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "installer_util_unittests",
- {
- "test": "interactive_ui_tests",
- "swarming": {
- "can_use_on_swarming_builders": true,
- "shards": 2
- }
- },
- "ipc_tests",
- "jingle_unittests",
- "keyboard_unittests",
- {
- "test": "media_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "message_center_unittests",
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
- {
- "test": "net_unittests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- {
- "test": "sync_integration_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "sql_unittests",
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
- {
- "test": "unit_tests",
- "swarming": {
- "can_use_on_swarming_builders": true
- }
- },
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
],
"scripts": [
{
@@ -630,146 +847,217 @@
},
"Win7 Tests (dbg)(1)": {
"gtest_tests": [
- "accessibility_unittests",
{
- "test": "ash_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
- "app_shell_unittests",
- "aura_unittests",
{
- "test": "base_unittests",
+ "test": "app_shell_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ash_unittests"
},
{
- "test": "browser_tests",
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 20
- }
+ },
+ "test": "browser_tests"
},
- "cacheinvalidation_unittests",
{
- "test": "cast_unittests",
+ "test": "cacheinvalidation_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
- "chromedriver_unittests",
- "chrome_elf_unittests",
{
- "test": "components_unittests",
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
- "compositor_unittests",
{
- "test": "content_browsertests",
+ "test": "compositor_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "courgette_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "courgette_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
- "events_unittests",
{
- "test": "extensions_browsertests",
+ "test": "events_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
- "extensions_unittests",
- "gcm_unit_tests",
{
- "test": "gpu_unittests",
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
- "installer_util_unittests",
{
- "test": "interactive_ui_tests",
+ "test": "installer_util_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 4
- }
+ },
+ "test": "interactive_ui_tests"
},
- "ipc_tests",
- "jingle_unittests",
{
- "test": "media_unittests",
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
- "mojo_common_unittests",
- "mojo_public_bindings_unittests",
- "mojo_public_environment_unittests",
- "mojo_public_system_unittests",
- "mojo_public_utility_unittests",
- "mojo_system_unittests",
- "nacl_loader_unittests",
{
- "test": "net_unittests",
+ "test": "mojo_common_unittests"
+ },
+ {
+ "test": "mojo_public_bindings_unittests"
+ },
+ {
+ "test": "mojo_public_environment_unittests"
+ },
+ {
+ "test": "mojo_public_system_unittests"
+ },
+ {
+ "test": "mojo_public_utility_unittests"
+ },
+ {
+ "test": "mojo_system_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
- "ppapi_unittests",
- "printing_unittests",
- "remoting_unittests",
- "sbox_unittests",
- "sbox_integration_tests",
- "sbox_validation_tests",
- "sql_unittests",
{
- "test": "sync_integration_tests",
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "sync_integration_tests"
},
- "sync_unit_tests",
- "ui_base_unittests",
- "ui_touch_selection_unittests",
{
- "test": "unit_tests",
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "unit_tests"
},
- "url_unittests",
- "views_unittests",
- "wm_unittests",
- "skia_unittests"
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
],
"scripts": [
{
@@ -784,14 +1072,372 @@
},
"Win8 Aura": {
"gtest_tests": [
- "views_unittests",
- "wm_unittests",
- "aura_unittests",
+ {
+ "test": "ash_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "test": "content_browsertests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ]
+ },
+ "Win8 GN": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
"ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
"compositor_unittests",
"content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
"events_unittests",
- "ui_touch_selection_unittests"
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "Win8 GN (dbg)": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "XP Tests (1)": {
+ "gtest_tests": [
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "accessibility_unittests"
+ },
+ {
+ "test": "app_shell_unittests"
+ },
+ {
+ "test": "aura_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "base_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ },
+ "test": "browser_tests"
+ },
+ {
+ "test": "cacheinvalidation_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cast_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "cc_unittests"
+ },
+ {
+ "test": "chrome_elf_unittests"
+ },
+ {
+ "test": "chromedriver_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "components_unittests"
+ },
+ {
+ "test": "compositor_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_browsertests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "content_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "courgette_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "crypto_unittests"
+ },
+ {
+ "test": "events_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "extensions_browsertests"
+ },
+ {
+ "test": "extensions_unittests"
+ },
+ {
+ "test": "gcm_unit_tests"
+ },
+ {
+ "test": "gfx_unittests"
+ },
+ {
+ "test": "google_apis_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "gpu_unittests"
+ },
+ {
+ "test": "installer_util_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ },
+ "test": "interactive_ui_tests"
+ },
+ {
+ "test": "ipc_mojo_unittests"
+ },
+ {
+ "test": "ipc_tests"
+ },
+ {
+ "test": "jingle_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "media_unittests"
+ },
+ {
+ "test": "nacl_loader_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "net_unittests"
+ },
+ {
+ "test": "ppapi_unittests"
+ },
+ {
+ "test": "printing_unittests"
+ },
+ {
+ "test": "remoting_unittests"
+ },
+ {
+ "test": "sbox_integration_tests"
+ },
+ {
+ "test": "sbox_unittests"
+ },
+ {
+ "test": "sbox_validation_tests"
+ },
+ {
+ "test": "skia_unittests"
+ },
+ {
+ "test": "sql_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "sync_integration_tests"
+ },
+ {
+ "test": "sync_unit_tests"
+ },
+ {
+ "test": "ui_base_unittests"
+ },
+ {
+ "test": "ui_touch_selection_unittests"
+ },
+ {
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ },
+ "test": "unit_tests"
+ },
+ {
+ "test": "url_unittests"
+ },
+ {
+ "test": "views_unittests"
+ },
+ {
+ "test": "wm_unittests"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "telemetry_unittests",
+ "script": "telemetry_unittests.py"
+ },
+ {
+ "name": "telemetry_perf_unittests",
+ "script": "telemetry_perf_unittests.py"
+ },
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
]
}
}
diff --git a/testing/buildbot/chromium_memory_trybot.json b/testing/buildbot/chromium_memory_trybot.json
index c794785..c58d2de 100644
--- a/testing/buildbot/chromium_memory_trybot.json
+++ b/testing/buildbot/chromium_memory_trybot.json
@@ -2,109 +2,113 @@
"gtest_tests": [
"accessibility_unittests",
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 10
- }
+ },
+ "test": "browser_tests"
},
"cacheinvalidation_unittests",
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
{
- "test": "components_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_browsertests"
},
{
- "test": "components_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
"device_unittests",
{
- "test": "display_unittests",
- "platforms": ["linux"]
+ "platforms": [
+ "linux"
+ ],
+ "test": "display_unittests"
},
"extensions_unittests",
"gcm_unit_tests",
"gfx_unittests",
"google_apis_unittests",
{
- "test": "gpu_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "interactive_ui_tests"
},
"ipc_tests",
"jingle_unittests",
{
- "test": "media_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
{
- "test": "net_unittests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "net_unittests"
},
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
{
- "test": "sandbox_linux_unittests",
- "platforms": ["linux"]
+ "platforms": [
+ "linux"
+ ],
+ "test": "sandbox_linux_unittests"
},
"skia_unittests",
"sql_unittests",
"sync_unit_tests",
"ui_base_unittests",
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "unit_tests"
},
"url_unittests"
]
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index 065de53..d42d551 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -2,25 +2,32 @@
"compile_targets": [
"all"
],
+ "filter_compile_builders": [
+ "win_chromium_compile_dbg",
+ "win_chromium_rel_swarming",
+ "win_chromium_x64_rel_swarming",
+ "win8_chromium_rel"
+ ],
"gtest_tests": [
{
- "test": "accessibility_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "accessibility_unittests"
},
{
- "test": "app_installer_unittests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "app_installer_unittests"
},
{
- "test": "app_list_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "app_list_unittests"
},
{
- "test": "ash_unittests",
"chromium_configs": [
"chromium_chromeos",
"chromium_chromeos_clang",
@@ -28,155 +35,183 @@
],
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ash_unittests"
},
{
- "test": "ash_unittests",
- "platforms": ["win"],
+ "platforms": [
+ "win"
+ ],
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ash_unittests"
},
{
- "test": "base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "base_unittests"
},
{
- "test": "browser_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 8
- }
+ },
+ "test": "browser_tests"
},
"cacheinvalidation_unittests",
{
- "test": "cast_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cast_unittests"
},
{
- "test": "cc_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "cc_unittests"
},
"chromedriver_unittests",
{
- "test": "chromevox_tests",
"chromium_configs": [
"chromium_chromeos",
"chromium_chromeos_clang",
"chromium_chromeos_ozone"
- ]
+ ],
+ "test": "chromevox_tests"
},
{
- "test": "chrome_elf_unittests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "chrome_elf_unittests"
},
{
- "test": "components_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_browsertests"
},
{
- "test": "components_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "components_unittests"
},
{
- "test": "compositor_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "compositor_unittests"
},
{
- "test": "courgette_unittests",
"can_use_on_swarming_builders": true,
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "courgette_unittests"
},
{
- "test": "content_browsertests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_browsertests"
},
{
- "test": "content_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "content_unittests"
},
{
- "test": "crypto_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "crypto_unittests"
},
{
- "test": "dbus_unittests",
- "platforms": ["linux"]
+ "platforms": [
+ "linux"
+ ],
+ "test": "dbus_unittests"
},
"device_unittests",
{
- "test": "events_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "events_unittests"
},
{
- "test": "extensions_unittests",
- "platforms": ["win", "mac", "linux"]
+ "platforms": [
+ "win",
+ "mac",
+ "linux"
+ ],
+ "test": "extensions_unittests"
},
"gcm_unit_tests",
{
- "test": "gfx_unittests",
+ "chromium_configs": [
+ "chromium_chromeos",
+ "chromium_chromeos_clang",
+ "chromium_chromeos_ozone"
+ ],
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gfx_unittests"
},
"google_apis_unittests",
{
- "test": "gpu_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "gpu_unittests"
},
{
- "test": "interactive_ui_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "interactive_ui_tests"
},
{
- "test": "installer_util_unittests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "installer_util_unittests"
},
{
- "test": "ipc_mojo_unittests",
- "platforms": ["linux"]
+ "platforms": [
+ "linux"
+ ],
+ "test": "ipc_mojo_unittests"
},
"ipc_tests",
"jingle_unittests",
{
- "test": "keyboard_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "keyboard_unittests"
},
"media_perftests",
{
- "test": "media_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "media_unittests"
},
{
- "test": "message_center_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "message_center_unittests"
},
"mojo_common_unittests",
"mojo_public_bindings_unittests",
@@ -186,127 +221,153 @@
"mojo_system_unittests",
"nacl_loader_unittests",
{
- "test": "net_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "net_unittests"
},
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
{
- "test": "sbox_integration_tests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "sbox_integration_tests"
},
{
- "test": "sbox_validation_tests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "sbox_validation_tests"
},
{
- "test": "sbox_unittests",
- "platforms": ["win"]
+ "platforms": [
+ "win"
+ ],
+ "test": "sbox_unittests"
},
"sql_unittests",
{
- "test": "sync_integration_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 3
- }
+ },
+ "test": "sync_integration_tests"
},
"sync_unit_tests",
{
- "test": "ui_base_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ui_base_unittests"
},
{
- "test": "ui_touch_selection_unittests",
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "ui_touch_selection_unittests"
},
{
- "test": "unit_tests",
"swarming": {
"can_use_on_swarming_builders": true,
"shards": 2
- }
+ },
+ "test": "unit_tests"
},
{
- "test": "ui_chromeos_unittests",
- "platforms": ["linux"],
"chromium_configs": [
"chromium_chromeos",
"chromium_chromeos_clang",
"chromium_chromeos_ozone"
- ]
+ ],
+ "platforms": [
+ "linux"
+ ],
+ "test": "ui_chromeos_unittests"
},
"url_unittests",
"skia_unittests",
{
- "test": "wm_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "wm_unittests"
},
{
- "test": "extensions_browsertests",
- "platforms": ["linux", "win"],
+ "platforms": [
+ "linux",
+ "win"
+ ],
"swarming": {
"can_use_on_swarming_builders": true
- }
+ },
+ "test": "extensions_browsertests"
},
{
- "test": "app_shell_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "app_shell_unittests"
},
{
- "test": "aura_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "aura_unittests"
},
{
- "test": "views_unittests",
- "platforms": ["linux", "win"]
+ "platforms": [
+ "linux",
+ "win"
+ ],
+ "test": "views_unittests"
},
{
- "test": "sandbox_linux_unittests",
- "platforms": ["linux"],
- "args": ["--test-launcher-print-test-stdio=always"]
+ "args": [
+ "--test-launcher-print-test-stdio=always"
+ ],
+ "platforms": [
+ "linux"
+ ],
+ "test": "sandbox_linux_unittests"
},
{
- "test": "sandbox_mac_unittests",
- "platforms": ["mac"]
+ "platforms": [
+ "mac"
+ ],
+ "test": "sandbox_mac_unittests"
},
{
- "test": "chromeos_unittests",
- "platforms": ["linux"],
"chromium_configs": [
"chromium_chromeos",
"chromium_chromeos_clang",
"chromium_chromeos_ozone"
- ]
+ ],
+ "platforms": [
+ "linux"
+ ],
+ "test": "chromeos_unittests"
},
{
- "test": "display_unittests",
- "platforms": ["linux"]
+ "platforms": [
+ "linux"
+ ],
+ "test": "display_unittests"
},
{
- "test": "ozone_unittests",
- "platforms": ["linux"],
- "chromium_configs": ["chromium_chromeos_ozone"]
+ "chromium_configs": [
+ "chromium_chromeos_ozone"
+ ],
+ "platforms": [
+ "linux"
+ ],
+ "test": "ozone_unittests"
}
],
-
- "non_filter_builders": [
- ],
-
- "non_filter_tests_builders": [
- ],
-
- "filter_compile_builders": [
- "win_chromium_compile_dbg",
- "win_chromium_rel_swarming",
- "win_chromium_x64_rel_swarming",
- "win8_chromium_rel"
- ]
+ "non_filter_builders": [],
+ "non_filter_tests_builders": []
}
diff --git a/testing/buildbot/client.v8.json b/testing/buildbot/client.v8.json
new file mode 100644
index 0000000..2f43da0
--- /dev/null
+++ b/testing/buildbot/client.v8.json
@@ -0,0 +1,64 @@
+{
+ "V8 Android GN (dbg)": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "V8 Linux GN": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "nacl_loader_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": []
+ }
+}
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
new file mode 100755
index 0000000..bc362fd
--- /dev/null
+++ b/testing/buildbot/manage.py
@@ -0,0 +1,193 @@
+#!/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.
+
+"""Toolbox to manage all the json files in this directory.
+
+It can reformat them in their canonical format or ensures they are well
+formatted.
+"""
+
+import argparse
+import collections
+import glob
+import json
+import os
+import subprocess
+import sys
+
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR))
+sys.path.insert(0, os.path.join(SRC_DIR, 'third_party', 'colorama', 'src'))
+
+import colorama
+
+
+SKIP = {
+ # These are not 'builders'.
+ 'compile_targets', 'gtest_tests', 'filter_compile_builders',
+ 'non_filter_builders', 'non_filter_tests_builders',
+
+ # These are not supported on Swarming yet.
+ # http://crbug.com/472205
+ 'Chromium Mac 10.10',
+ # http://crbug.com/441429
+ 'Linux Trusty (32)', 'Linux Trusty (dbg)(32)',
+
+ # One off builders. Note that Swarming does support ARM.
+ 'Linux ARM Cross-Compile',
+ 'Site Isolation Linux',
+ 'Site Isolation Win',
+}
+
+
+def upgrade_test(test):
+ """Converts from old style string to new style dict."""
+ if isinstance(test, basestring):
+ return {'test': test}
+ assert isinstance(test, dict)
+ return test
+
+
+def get_isolates():
+ """Returns the list of all isolate files."""
+ files = subprocess.check_output(['git', 'ls-files'], cwd=SRC_DIR).splitlines()
+ return [os.path.basename(f) for f in files if f.endswith('.isolate')]
+
+
+def main():
+ colorama.init()
+ parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument(
+ '-c', '--check', action='store_true', help='Only check the files')
+ group.add_argument(
+ '--convert', action='store_true',
+ help='Convert a test to run on Swarming everywhere')
+ group.add_argument(
+ '--remaining', action='store_true',
+ help='Count the number of tests not yet running on Swarming')
+ group.add_argument(
+ '-w', '--write', action='store_true', help='Rewrite the files')
+ parser.add_argument(
+ 'test_name', nargs='?',
+ help='The test name to print which configs to update; only to be used '
+ 'with --remaining')
+ args = parser.parse_args()
+
+ if args.convert or args.remaining:
+ isolates = get_isolates()
+
+ if args.convert:
+ if not args.test_name:
+ parser.error('A test name is required with --convert')
+ if args.test_name + '.isolate' not in isolates:
+ parser.error('Create %s.isolate first' % args.test_name)
+
+ # Stats when running in --remaining mode;
+ tests_location = collections.defaultdict(
+ lambda: {
+ 'count_run_local': 0, 'count_run_on_swarming': 0, 'local_configs': {}
+ })
+
+ result = 0
+ for filepath in glob.glob(os.path.join(THIS_DIR, '*.json')):
+ filename = os.path.basename(filepath)
+ with open(filepath) as f:
+ content = f.read()
+ try:
+ config = json.loads(content)
+ except ValueError as e:
+ print "Exception raised while checking %s: %s" % (filepath, e)
+ raise
+ for builder, data in sorted(config.iteritems()):
+ if builder in SKIP:
+ # Oddities.
+ continue
+
+ if not isinstance(data, dict):
+ print('%s: %s is broken: %s' % (filename, builder, data))
+ continue
+
+ if 'gtest_tests' in data:
+ config[builder]['gtest_tests'] = sorted(
+ (upgrade_test(l) for l in data['gtest_tests']),
+ key=lambda x: x['test'])
+
+ if args.remaining:
+ for test in data['gtest_tests']:
+ name = test['test']
+ if test.get('swarming', {}).get('can_use_on_swarming_builders'):
+ tests_location[name]['count_run_on_swarming'] += 1
+ else:
+ tests_location[name]['count_run_local'] += 1
+ tests_location[name]['local_configs'].setdefault(
+ filename, []).append(builder)
+ elif args.convert:
+ for test in data['gtest_tests']:
+ if test['test'] != args.test_name:
+ continue
+ test.setdefault('swarming', {})
+ if not test['swarming'].get('can_use_on_swarming_builders'):
+ print('- %s: %s' % (filename, builder))
+ test['swarming']['can_use_on_swarming_builders'] = True
+
+ expected = json.dumps(
+ config, sort_keys=True, indent=2, separators=(',', ': ')) + '\n'
+ if content != expected:
+ result = 1
+ if args.write or args.convert:
+ with open(filepath, 'wb') as f:
+ f.write(expected)
+ if args.write:
+ print('Updated %s' % filename)
+ else:
+ print('%s is not in canonical format' % filename)
+
+ if args.remaining:
+ if args.test_name:
+ if args.test_name not in tests_location:
+ print('Unknown test %s' % args.test_name)
+ return 1
+ for config, builders in sorted(
+ tests_location[args.test_name]['local_configs'].iteritems()):
+ print('%s:' % config)
+ for builder in sorted(builders):
+ print(' %s' % builder)
+ else:
+ l = max(map(len, tests_location))
+ print('%-*s%sLocal %sSwarming %sMissing isolate' %
+ (l, 'Test', colorama.Fore.RED, colorama.Fore.GREEN,
+ colorama.Fore.MAGENTA))
+ total_local = 0
+ total_swarming = 0
+ for name, location in sorted(tests_location.iteritems()):
+ if not location['count_run_on_swarming']:
+ c = colorama.Fore.RED
+ elif location['count_run_local']:
+ c = colorama.Fore.YELLOW
+ else:
+ c = colorama.Fore.GREEN
+ total_local += location['count_run_local']
+ total_swarming += location['count_run_on_swarming']
+ missing_isolate = ''
+ if name + '.isolate' not in isolates:
+ missing_isolate = colorama.Fore.MAGENTA + '*'
+ print('%s%-*s %4d %4d %s' %
+ (c, l, name, location['count_run_local'],
+ location['count_run_on_swarming'], missing_isolate))
+
+ total = total_local + total_swarming
+ p_local = 100. * total_local / total
+ p_swarming = 100. * total_swarming / total
+ print('%s%-*s %4d (%4.1f%%) %4d (%4.1f%%)' %
+ (colorama.Fore.WHITE, l, 'Total:', total_local, p_local,
+ total_swarming, p_swarming))
+ print('%-*s %4d' % (l, 'Total executions:', total))
+ return result
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index ed45362..f5c6710 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -1,4 +1,9 @@
{
+ "android_webview": {
+ "exclusions": [
+ "android_webview/.*"
+ ]
+ },
"base": {
"exclusions": [
".*isolate",
@@ -16,11 +21,6 @@
"tools/whitespace.txt"
]
},
- "android_webview": {
- "exclusions": [
- "android_webview/.*"
- ]
- },
"chromium": {
"exclusions": [
"chrome/test/data/.*",
@@ -37,6 +37,7 @@
"third_party/zlib/google/test/data/.*",
"tools/clang/scripts/update.py",
"tools/clang/scripts/update.sh",
+ "tools/mb/.*",
"tools/metrics/histograms/histograms.xml",
"tools/perf/.*",
"tools/telemetry/.*"
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json
new file mode 100644
index 0000000..fe4d275
--- /dev/null
+++ b/testing/buildbot/tryserver.blink.json
@@ -0,0 +1,65 @@
+{
+ "android_chromium_gn_compile_rel": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "linux_chromium_gn_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "chromedriver_unittests",
+ "chromeos_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_chromeos_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ }
+}
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index 2c63c08..6d3c6d4 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -1,2 +1,200 @@
{
+ "android_chromium_gn_compile_dbg": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "android_chromium_gn_compile_rel": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "linux_chromium_gn_chromeos_dbg": {
+ "additional_compile_targets": [
+ "net_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "linux_chromium_gn_chromeos_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "chromedriver_unittests",
+ "chromeos_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_chromeos_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "linux_chromium_gn_dbg": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "linux_chromium_gn_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "nacl_loader_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ }
}
diff --git a/testing/buildbot/tryserver.chromium.mac.json b/testing/buildbot/tryserver.chromium.mac.json
index 2c63c08..4a46f9a 100644
--- a/testing/buildbot/tryserver.chromium.mac.json
+++ b/testing/buildbot/tryserver.chromium.mac.json
@@ -1,2 +1,72 @@
{
+ "mac_chromium_gn_dbg": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "base_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "crypto_unittests",
+ "gcm_unit_tests",
+ "gn_unittests",
+ "gpu_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "url_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "mac_chromium_gn_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "base_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "crypto_unittests",
+ "gcm_unit_tests",
+ "gn_unittests",
+ "gpu_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "url_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ }
}
diff --git a/testing/buildbot/tryserver.chromium.perf.json b/testing/buildbot/tryserver.chromium.perf.json
index 2c63c08..0967ef4 100644
--- a/testing/buildbot/tryserver.chromium.perf.json
+++ b/testing/buildbot/tryserver.chromium.perf.json
@@ -1,2 +1 @@
-{
-}
+{}
diff --git a/testing/buildbot/tryserver.chromium.win.json b/testing/buildbot/tryserver.chromium.win.json
index 2c63c08..6710973 100644
--- a/testing/buildbot/tryserver.chromium.win.json
+++ b/testing/buildbot/tryserver.chromium.win.json
@@ -1,2 +1,250 @@
{
+ "win8_chromium_gn_dbg": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "win8_chromium_gn_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "win_chromium_gn_x64_dbg": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ },
+ "win_chromium_gn_x64_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "ash_unittests",
+ "aura_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chrome",
+ "chrome_elf_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "compositor_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "courgette_unittests",
+ "crypto_unittests",
+ "device_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "keyboard_unittests",
+ "media_unittests",
+ "message_center_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "sbox_integration_tests",
+ "sbox_unittests",
+ "sbox_validation_tests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": [
+ {
+ "test": "base_unittests"
+ }
+ ]
+ }
}
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json
new file mode 100644
index 0000000..a92d05d
--- /dev/null
+++ b/testing/buildbot/tryserver.v8.json
@@ -0,0 +1,64 @@
+{
+ "v8_android_chromium_gn_dbg": {
+ "additional_compile_targets": [
+ "chrome_shell_apk"
+ ],
+ "gtest_tests": []
+ },
+ "v8_linux_chromium_gn_rel": {
+ "additional_compile_targets": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ "browser_tests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_browsertests",
+ "components_unittests",
+ "content_browsertests",
+ "content_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_browsertests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "gn_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "interactive_ui_tests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "nacl_loader_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_integration_tests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "unit_tests",
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "gtest_tests": []
+ }
+}
diff --git a/testing/chromoting/browser_test_commands_linux.txt b/testing/chromoting/browser_test_commands_linux.txt
index 95f076f..c9ecb29 100644
--- a/testing/chromoting/browser_test_commands_linux.txt
+++ b/testing/chromoting/browser_test_commands_linux.txt
@@ -14,4 +14,5 @@
/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Cancel_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Update_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Invalid_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123457 --override-user-data-dir=/tmp/chromoting_test_profile
-/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=FullscreenBrowserTest.MANUAL_Me2Me_Bump_Scroll --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
\ No newline at end of file
+/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=FullscreenBrowserTest.MANUAL_Me2Me_Bump_Scroll --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
+cd ../../remoting/internal/config && /usr/bin/python ./is_valid_json.py
\ No newline at end of file
diff --git a/testing/chromoting/browser_tests_launcher.py b/testing/chromoting/browser_tests_launcher.py
index a265f56..2fceb7c 100644
--- a/testing/chromoting/browser_tests_launcher.py
+++ b/testing/chromoting/browser_tests_launcher.py
@@ -21,15 +21,19 @@
CRD_ID = 'chrome-remote-desktop' # Used in a few file/folder names
CHROMOTING_HOST_PATH = '/opt/google/chrome-remote-desktop/chrome-remote-desktop'
TEST_FAILURE = False
+FAILING_TESTS = ''
+HOST_READY_INDICATOR = 'Host ready to receive connections.'
def LaunchBTCommand(command):
- global TEST_FAILURE
+ global TEST_FAILURE, FAILING_TESTS
results = RunCommandInSubProcess(command)
# Check that the test passed.
if SUCCESS_INDICATOR not in results:
TEST_FAILURE = True
+ # Add this command-line to list of tests that failed.
+ FAILING_TESTS += command
def RunCommandInSubProcess(command):
@@ -43,17 +47,16 @@
cmd_line = [command]
try:
- p = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, shell=True)
- results, error = p.communicate()
+ results = subprocess.check_output(cmd_line, stderr=subprocess.STDOUT,
+ shell=True)
except subprocess.CalledProcessError, e:
- raise Exception('Exception %s running command %s\nError: %s' %
- (e, command, error))
- else:
+ results = e.output
+ finally:
print results
return results
-def TestCleanUp(user_profile_dir):
+def TestMachineCleanup(user_profile_dir):
"""Cleans up test machine so as not to impact other tests.
Args:
@@ -81,6 +84,9 @@
Args:
cfg_file: location of test account's host-config file.
+
+ Raises:
+ Exception: if host did not start properly.
"""
# First get home directory on current machine.
@@ -98,8 +104,31 @@
config_file_src,
os.path.join(default_config_file_location, default_config_file_name))
- # Finally, start chromoting host.
- RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --start')
+ # Make sure chromoting host is running.
+ if not RestartMe2MeHost():
+ # Host start failed. Don't run any tests.
+ raise Exception('Host restart failed.')
+
+
+def RestartMe2MeHost():
+ """Stops and starts the Me2Me host on the test machine.
+
+ Waits to confirm that host is ready to receive connections before returning.
+
+ Returns:
+ True: if HOST_READY_INDICATOR is found in stdout, indicating host is ready.
+ False: if HOST_READY_INDICATOR not found in stdout.
+ """
+
+ # Stop chromoting host.
+ RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --stop')
+ # Start chromoting host.
+ results = RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --start')
+ # Confirm that the start process completed, and we got:
+ # "Host ready to receive connections." in the log.
+ if HOST_READY_INDICATOR not in results:
+ return False
+ return True
def SetupUserProfileDir(me2me_manifest_file, it2me_manifest_file,
@@ -133,7 +162,45 @@
shutil.copyfile(manifest_file_src, manifest_file_dest)
-def main():
+def main(args):
+
+ InitialiseTestMachineForLinux(args.cfg_file)
+
+ with open(args.commands_file) as f:
+ for line in f:
+ # Reset the user profile directory to start each test with a clean slate.
+ SetupUserProfileDir(args.me2me_manifest_file, args.it2me_manifest_file,
+ args.user_profile_dir)
+
+ # Replace the PROD_DIR value in the command-line with
+ # the passed in value.
+ line = line.replace(PROD_DIR_ID, args.prod_dir)
+ # Launch specified command line for test.
+ LaunchBTCommand(line)
+ # After each test, stop+start me2me host process.
+ if not RestartMe2MeHost():
+ # Host restart failed. Don't run any more tests.
+ raise Exception('Host restart failed.')
+
+ # All tests completed. Include host-logs in the test results.
+ host_log_contents = ''
+ # There should be only 1 log file, as we delete logs on test completion.
+ # Loop through matching files, just in case there are more.
+ for log_file in glob.glob('/tmp/chrome_remote_desktop_*'):
+ with open(log_file, 'r') as log:
+ host_log_contents += '\nHOST LOG %s\n CONTENTS:\n%s' % (
+ log_file, log.read())
+ print host_log_contents
+
+ # Was there any test failure?
+ if TEST_FAILURE:
+ print '++++++++++AT LEAST 1 TEST FAILED++++++++++'
+ print FAILING_TESTS.rstrip('\n')
+ print '++++++++++++++++++++++++++++++++++++++++++'
+ raise Exception('At least one test failed.')
+
+if __name__ == '__main__':
+
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--commands_file',
help='path to file listing commands to be launched.')
@@ -148,36 +215,9 @@
parser.add_argument(
'-u', '--user_profile_dir',
help='path to user-profile-dir, used by connect-to-host tests.')
-
- args = parser.parse_args()
-
- InitialiseTestMachineForLinux(args.cfg_file)
-
- with open(args.commands_file) as f:
- for line in f:
- # Reset the user profile directory to start each test with a clean slate.
- SetupUserProfileDir(args.me2me_manifest_file, args.it2me_manifest_file,
- args.user_profile_dir)
-
- # Replace the PROD_DIR value in the command-line with
- # the passed in value.
- line = line.replace(PROD_DIR_ID, args.prod_dir)
- LaunchBTCommand(line)
-
- # Was there any test failure?
- if TEST_FAILURE:
- # Obtain contents of Chromoting host logs.
- log_contents = ''
- # There should be only 1 log file, as we delete logs on test completion.
- # Loop through matching files, just in case there are more.
- for log_file in glob.glob('/tmp/chrome_remote_desktop_*'):
- with open(log_file, 'r') as log:
- log_contents += '\nHOST LOG %s\n CONTENTS:\n%s' % (log_file, log.read())
- print log_contents
- raise Exception('At least one test failed.')
-
- # Now, stop host, and cleanup user-profile-dir
- TestCleanUp(args.user_profile_dir)
-
-if __name__ == '__main__':
- main()
+ command_line_args = parser.parse_args()
+ try:
+ main(command_line_args)
+ finally:
+ # Stop host and cleanup user-profile-dir.
+ TestMachineCleanup(command_line_args.user_profile_dir)
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate
index 8dcbe5d..0bf8b7a 100644
--- a/testing/chromoting/chromoting_integration_tests.isolate
+++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -31,6 +31,10 @@
'<(PRODUCT_DIR)/remoting/com.google.chrome.remote_desktop.json',
'<(PRODUCT_DIR)/remoting/com.google.chrome.remote_assistance.json',
'<(PRODUCT_DIR)/remoting-me2me-host.deb',
+ '<(PRODUCT_DIR)/nacl_helper',
+ '<(PRODUCT_DIR)/nacl_helper_bootstrap',
+ '<(PRODUCT_DIR)/pnacl/',
+ '../../remoting/internal/config/',
],
},
}],
diff --git a/testing/chromoting/dependencies.gypi b/testing/chromoting/dependencies.gypi
new file mode 100644
index 0000000..10013d3
--- /dev/null
+++ b/testing/chromoting/dependencies.gypi
@@ -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.
+
+# This file is meant to be included by chromoting's integration_tests.
+
+{
+ 'dependencies': [
+ '../../chrome/chrome.gyp:browser_tests',
+ '../../remoting/remoting.gyp:remoting_webapp_v1',
+ '../../remoting/remoting.gyp:remoting_webapp_v2',
+ ],
+ 'type': 'none',
+ 'includes': [
+ '../../build/isolate.gypi',
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'dependencies': [
+ '../../remoting/remoting.gyp:remoting_me2me_host_archive',
+ '../../remoting/internal/app_remoting_all.gyp:app_remoting_all_apps',
+ ],
+ }], # OS=="linux"
+ ],
+}
diff --git a/testing/chromoting/integration_tests.gyp b/testing/chromoting/integration_tests.gyp
index b50c3c6..c3f7912 100644
--- a/testing/chromoting/integration_tests.gyp
+++ b/testing/chromoting/integration_tests.gyp
@@ -2,58 +2,28 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# TODO: Factor out all of the common items across the test targets into a
-# single .gypi file that can be included by each test target.
-
{
'conditions': [
['archive_chromoting_tests==1', {
'targets': [
{
'target_name': 'chromoting_integration_tests_run',
- 'type': 'none',
- 'dependencies': [
- '../../chrome/chrome.gyp:browser_tests',
- '../../remoting/remoting.gyp:remoting_webapp_v1',
- '../../remoting/remoting.gyp:remoting_webapp_v2',
- ],
'includes': [
- '../../build/isolate.gypi',
+ './dependencies.gypi',
],
'sources': [
'chromoting_integration_tests.isolate',
],
- 'conditions': [
- ['OS=="linux"', {
- 'dependencies': [
- '../../remoting/remoting.gyp:remoting_me2me_host_archive',
- '../../remoting/webapp/app_remoting/internal/app_remoting_all.gyp:app_remoting_all_apps',
- ],
- }], # OS=="linux"
- ],
}, # target_name: 'chromoting_integration_tests_run'
{
'target_name': 'chromoting_multi_machine_example_test',
- 'type': 'none',
- 'dependencies': [
- '../../chrome/chrome.gyp:browser_tests',
- '../../remoting/remoting.gyp:remoting_webapp_v1',
- '../../remoting/remoting.gyp:remoting_webapp_v2',
- ],
'includes': [
- '../../build/isolate.gypi',
+ './dependencies.gypi',
],
'sources': [
'multi_machine_example/example_test_controller.isolate',
'multi_machine_example/example_task.isolate',
],
- 'conditions': [
- ['OS=="linux"', {
- 'dependencies': [
- '../../remoting/remoting.gyp:remoting_me2me_host_archive',
- ],
- }], # OS=="linux"
- ],
}, # target_name: 'chromoting_multi_machine_example_test'
],
}],
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json
index 8c0a2e7..aefd3c7 100644
--- a/testing/commit_queue/config.json
+++ b/testing/commit_queue/config.json
@@ -1,14 +1,10 @@
{
"commit_burst_delay": 60,
"commit_user": "commit-bot@chromium.org",
- "committer_project": "chromium",
"cq_status_url": "https://chromium-cq-status.appspot.com",
"git_repo_url": "https://chromium.googlesource.com/chromium/src",
"hide_ref_in_committed_msg": true,
"max_commit_burst": 2,
- "project_bases": [
- ".*"
- ],
"project_bases_legacy": [
"^svn\\:\\/\\/svn\\.chromium\\.org\\/chrome/trunk/src(|/.*)$",
"^svn\\:\\/\\/chrome\\-svn\\/chrome/trunk/src(|/.*)$",
@@ -26,8 +22,6 @@
"skip_throttle_users": [
"commit-bot@chromium.org"
],
- "tree_status_url": "https://chromium-status.appspot.com",
- "tryserver_url": "http://build.chromium.org/p/tryserver.chromium/",
"use_buildbucket_for_tryjobs": true,
"verifiers_no_patch": {
"experimental_try_job_verifier": {
@@ -39,12 +33,6 @@
"android_amp_rel_tests_recipe": [
"defaulttests"
],
- "cast_shell": [
- "defaulttests"
- ],
- "cast_shell_apk": [
- "defaulttests"
- ],
"linux_arm_compile": [
"defaulttests"
],
@@ -94,8 +82,12 @@
}
}
},
- "reviewer_lgtm_verifier": {},
- "tree_status_verifier": {},
+ "reviewer_lgtm_verifier": {
+ "committer_project": "chromium"
+ },
+ "tree_status_verifier": {
+ "tree_status_url": "https://chromium-status.appspot.com"
+ },
"try_job_verifier": {
"launched": {
"tryserver.chromium.linux": {
@@ -111,7 +103,13 @@
"android_clang_dbg_recipe": [
"defaulttests"
],
- "android_compile_rel": [
+ "android_compile_dbg": [
+ "defaulttests"
+ ],
+ "cast_shell_android": [
+ "defaulttests"
+ ],
+ "cast_shell_linux": [
"defaulttests"
],
"chromium_presubmit": [
@@ -181,5 +179,6 @@
}
}
}
- }
+ },
+ "version": 1
}
diff --git a/testing/iossim/OWNERS b/testing/iossim/OWNERS
index 7f8c2f8..1b3348e 100644
--- a/testing/iossim/OWNERS
+++ b/testing/iossim/OWNERS
@@ -1,3 +1,2 @@
-lliabraa@chromium.org
rohitrao@chromium.org
stuartmorgan@chromium.org
diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm
index 83cfe92..2f2af8d 100644
--- a/testing/iossim/iossim.mm
+++ b/testing/iossim/iossim.mm
@@ -850,7 +850,8 @@
NSString* appPath = nil;
NSString* appName = nil;
NSString* sdkVersion = nil;
- NSString* deviceName = IsRunningWithXcode6OrLater() ? @"iPhone 5" : @"iPhone";
+ NSString* deviceName =
+ IsRunningWithXcode6OrLater() ? @"iPhone 5s" : @"iPhone";
NSString* simHomePath = nil;
NSMutableArray* appArgs = [NSMutableArray array];
NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py
index c752e0f..6e7954b 100644
--- a/testing/legion/common_lib.py
+++ b/testing/legion/common_lib.py
@@ -26,7 +26,7 @@
argparse.ArgumentError if the --verbosity arg is incorrect.
"""
parser = argparse.ArgumentParser()
- logging_action = parser.add_argument('--verbosity', default='ERROR')
+ logging_action = parser.add_argument('--verbosity', default='INFO')
args, _ = parser.parse_known_args()
if args.verbosity not in LOGGING_LEVELS:
raise argparse.ArgumentError(
@@ -40,4 +40,4 @@
"""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)
+ return xmlrpclib.Server(addr, allow_none=True)
diff --git a/testing/legion/examples/hello_world/controller_test.py b/testing/legion/examples/hello_world/controller_test.py
index 37afcef..8253e9e 100755
--- a/testing/legion/examples/hello_world/controller_test.py
+++ b/testing/legion/examples/hello_world/controller_test.py
@@ -9,74 +9,69 @@
task 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 argparse
import logging
+import os
+import sys
import time
-import test_controller
+# Map the testing directory so we can import legion.legion_test.
+TESTING_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..', '..', '..', '..', 'testing')
+sys.path.append(TESTING_DIR)
+
+from legion import legion_test_case
-class ExampleTestController(test_controller.TestController):
+class ExampleTestController(legion_test_case.TestCase):
"""A simple example controller for a test."""
- def __init__(self):
- super(ExampleTestController, self).__init__()
- self.task1 = None
- self.task2 = None
+ @classmethod
+ def CreateTestTask(cls):
+ """Create a new task."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--task-hash')
+ parser.add_argument('--os', default='Ubuntu-14.04')
+ args, _ = parser.parse_known_args()
- def CreateTask(self, isolated_hash):
- """Create a task object and set the proper values."""
- task = self.CreateNewTask(
- isolated_hash=isolated_hash,
- dimensions={'os': 'Ubuntu-14.04', 'pool': 'Legion'}, priority=200,
- idle_timeout_secs=90, connection_timeout_secs=90,
- verbosity=logging.INFO,
- run_id=1)
+ task = cls.CreateTask(
+ isolated_hash=args.task_hash,
+ dimensions={'os': args.os},
+ idle_timeout_secs=90,
+ connection_timeout_secs=90,
+ verbosity=logging.DEBUG)
task.Create()
return task
- def SetUp(self):
- """Create the task machines and wait until they connect.
+ @classmethod
+ def setUpClass(cls):
+ """Creates the task machines and waits until they connect."""
+ cls.task1 = cls.CreateTestTask()
+ cls.task2 = cls.CreateTestTask()
+ cls.task1.WaitForConnection()
+ cls.task2.WaitForConnection()
- In this call the actual creation of the task machines is done in parallel
- by the system. The WaitForConnect calls are performed in series but will
- return as soon as the tasks connect.
- """
- parser = argparse.ArgumentParser()
- parser.add_argument('--task-hash')
- args, _ = parser.parse_known_args()
+ def testCallEcho(self):
+ """Tests rpc.Echo on a task."""
+ logging.info('Calling Echo on %s', self.task2.name)
+ self.assertEqual(self.task2.rpc.Echo('foo'), 'echo foo')
- self.task1 = self.CreateTask(args.task_hash)
- self.task2 = self.CreateTask(args.task_hash)
- self.task1.WaitForConnection()
- self.task2.WaitForConnection()
+ def testLaunchTaskBinary(self):
+ """Call task_test.py 'name' on the tasks."""
+ self.VerifyTaskBinaryLaunched(self.task1)
+ self.VerifyTaskBinaryLaunched(self.task2)
- def RunTest(self):
- """Main method to run the test code."""
- self.CallEcho(self.task1)
- self.CallEcho(self.task2)
- self.CallTaskTest(self.task1)
- self.CallTaskTest(self.task2)
-
- def CallEcho(self, task):
- """Call rpc.Echo on a task."""
- logging.info('Calling Echo on %s', task.name)
- logging.info(task.rpc.Echo(task.name))
-
- def CallTaskTest(self, task):
- """Call task_test.py name on a task."""
- logging.info('Calling Subprocess to run "./task_test.py %s"', task.name)
- proc = task.rpc.subprocess.Popen(['./task_test.py', task.name])
- task.rpc.subprocess.Wait(proc)
- retcode = task.rpc.subprocess.GetReturncode(proc)
- stdout = task.rpc.subprocess.ReadStdout(proc)
- stderr = task.rpc.subprocess.ReadStderr(proc)
- logging.info('retcode: %s, stdout: %s, stderr: %s', retcode, stdout, stderr)
+ def VerifyTaskBinaryLaunched(self, task):
+ logging.info(
+ 'Calling Process to run "./task_test.py %s"', task.name)
+ proc = task.Process(['./task_test.py', task.name])
+ proc.Wait()
+ self.assertEqual(proc.GetReturncode(), 0)
+ self.assertIn(task.name, proc.ReadStdout())
+ self.assertEquals(proc.ReadStderr(), '')
+ proc.Delete()
if __name__ == '__main__':
- ExampleTestController().RunController()
+ legion_test_case.main()
diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py
index 1a28ddd..cea871a 100755
--- a/testing/legion/examples/subprocess/subprocess_test.py
+++ b/testing/legion/examples/subprocess/subprocess_test.py
@@ -5,85 +5,91 @@
"""A host test module demonstrating interacting with remote subprocesses."""
-# Map the legion directory so we can import the host controller.
-import sys
-sys.path.append('../../')
-
import argparse
import logging
+import os
+import sys
import time
import xmlrpclib
-import test_controller
+# Map the testing directory so we can import legion.legion_test.
+TESTING_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..', '..', '..', '..', 'testing')
+sys.path.append(TESTING_DIR)
+
+from legion import legion_test_case
-class ExampleTestController(test_controller.TestController):
+class ExampleTestController(legion_test_case.TestCase):
"""An example controller using the remote subprocess functions."""
- def __init__(self):
- super(ExampleTestController, self).__init__()
- self.task = None
-
- def SetUp(self):
+ @classmethod
+ def setUpClass(cls):
"""Creates the task machine and waits until it connects."""
parser = argparse.ArgumentParser()
parser.add_argument('--task-hash')
+ parser.add_argument('--os', default='Ubuntu-14.04')
args, _ = parser.parse_known_args()
- self.task = self.CreateNewTask(
+ cls.task = cls.CreateTask(
isolated_hash=args.task_hash,
- dimensions={'os': 'Ubuntu-14.04', 'pool': 'Chromoting'},
- idle_timeout_secs=90, connection_timeout_secs=90,
+ dimensions={'os': args.os},
+ idle_timeout_secs=90,
+ connection_timeout_secs=90,
verbosity=logging.DEBUG)
- self.task.Create()
- self.task.WaitForConnection()
+ cls.task.Create()
+ cls.task.WaitForConnection()
- def RunTest(self):
- """Main method to run the test code."""
- self.TestLs()
- self.TestTerminate()
- self.TestMultipleProcesses()
+ def testMultipleProcesses(self):
+ """Tests that processes can be run and controlled simultaneously."""
+ start = time.time()
+ logging.info('Starting "sleep 10" and "sleep 20"')
+ sleep10 = self.task.Process(['sleep', '10'])
+ sleep20 = self.task.Process(['sleep', '20'])
- def TestMultipleProcesses(self):
+ logging.info('Waiting for sleep 10 to finish and verifying timing')
+ sleep10.Wait()
+ elapsed = time.time() - start
+ self.assertGreaterEqual(elapsed, 10)
+ self.assertLess(elapsed, 11)
+
+ logging.info('Waiting for sleep 20 to finish and verifying timing')
+ sleep20.Wait()
+ elapsed = time.time() - start
+ self.assertGreaterEqual(elapsed, 20)
+
+ sleep10.Delete()
+ sleep20.Delete()
+
+ def testTerminate(self):
+ """Tests that a process can be correctly terminated."""
start = time.time()
- sleep20 = self.task.rpc.subprocess.Process(['sleep', '20'])
- self.task.rpc.subprocess.Start(sleep20)
- sleep10 = self.task.rpc.subprocess.Process(['sleep', '10'])
- self.task.rpc.subprocess.Start(sleep10)
-
- self.task.rpc.subprocess.Wait(sleep10)
- elapsed = time.time() - start
- assert elapsed >= 10 and elapsed < 11
-
- self.task.rpc.subprocess.Wait(sleep20)
- elapsed = time.time() - start
- assert elapsed >= 20
-
- self.task.rpc.subprocess.Delete(sleep20)
- self.task.rpc.subprocess.Delete(sleep10)
-
- def TestTerminate(self):
- start = time.time()
- proc = self.task.rpc.subprocess.Process(['sleep', '20'])
- self.task.rpc.subprocess.Start(proc)
- self.task.rpc.subprocess.Terminate(proc)
+ logging.info('Starting "sleep 20"')
+ sleep20 = self.task.Process(['sleep', '20'])
+ logging.info('Calling Terminate()')
+ sleep20.Terminate()
try:
- self.task.rpc.subprocess.Wait(proc)
+ logging.info('Trying to wait for sleep 20 to complete')
+ sleep20.Wait()
except xmlrpclib.Fault:
pass
finally:
- self.task.rpc.subprocess.Delete(proc)
- assert time.time() - start < 20
+ sleep20.Delete()
+ logging.info('Checking to make sure sleep 20 was actually terminated')
+ self.assertLess(time.time() - start, 20)
- def TestLs(self):
- proc = self.task.rpc.subprocess.Process(['ls'])
- self.task.rpc.subprocess.Start(proc)
- self.task.rpc.subprocess.Wait(proc)
- assert self.task.rpc.subprocess.GetReturncode(proc) == 0
- assert 'task.isolate' in self.task.rpc.subprocess.ReadStdout(proc)
- self.task.rpc.subprocess.Delete(proc)
+ def testLs(self):
+ """Tests that the returned results from a process are correct."""
+ logging.info('Calling "ls"')
+ ls = self.task.Process(['ls'])
+ logging.info('Trying to wait for ls to complete')
+ ls.Wait()
+ logging.info('Checking that ls completed and returned the correct results')
+ self.assertEqual(ls.GetReturncode(), 0)
+ self.assertIn('task.isolate', ls.ReadStdout())
if __name__ == '__main__':
- ExampleTestController().RunController()
+ legion_test_case.main()
diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate
index 774b27a..18e0b3b 100644
--- a/testing/legion/legion.isolate
+++ b/testing/legion/legion.isolate
@@ -7,7 +7,9 @@
'files': [
'__init__.py',
'common_lib.py',
+ 'legion_test_case.py',
'legion.isolate',
+ 'process.py',
'rpc_methods.py',
'rpc_server.py',
'run_task.py',
diff --git a/testing/legion/legion_test_case.py b/testing/legion/legion_test_case.py
new file mode 100644
index 0000000..9514e8e
--- /dev/null
+++ b/testing/legion/legion_test_case.py
@@ -0,0 +1,135 @@
+# 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.
+
+"""Adds unittest-esque functionality to Legion."""
+
+import argparse
+import logging
+import sys
+import unittest
+
+#pylint: disable=relative-import
+import common_lib
+import task_controller
+import task_registration_server
+
+BANNER_WIDTH = 80
+
+
+class TestCase(unittest.TestCase):
+ """Test case class with added Legion support."""
+
+ _registration_server = None
+ _initialized = False
+
+ @classmethod
+ def __new__(cls, *args, **kwargs):
+ """Initialize the class and return a new instance."""
+ cls._InitializeClass()
+ return super(TestCase, cls).__new__(*args, **kwargs)
+
+ def __init__(self, test_name='runTest'):
+ super(TestCase, self).__init__(test_name)
+ method = getattr(self, test_name, None)
+ if method:
+ # Install the _RunTest method
+ self._TestMethod = method
+ setattr(self, test_name, self._RunTest)
+
+ def _RunTest(self):
+ """Runs the test method and provides banner info and error reporting."""
+ self._LogInfoBanner(self._testMethodName, self.shortDescription())
+ try:
+ return self._TestMethod()
+ except:
+ exc_info = sys.exc_info()
+ logging.error('', exc_info=exc_info)
+ raise exc_info[0], exc_info[1], exc_info[2]
+
+ @classmethod
+ def _InitializeClass(cls):
+ """Handles class level initialization.
+
+ There are 2 types of setup/teardown methods that always need to be run:
+ 1) Framework level setup/teardown
+ 2) Test case level setup/teardown
+
+ This method installs handlers in place of setUpClass and tearDownClass that
+ will ensure both types of setup/teardown methods are called correctly.
+ """
+ if cls._initialized:
+ return
+ cls._OriginalSetUpClassMethod = cls.setUpClass
+ cls.setUpClass = cls._HandleSetUpClass
+ cls._OriginalTearDownClassMethod = cls.tearDownClass
+ cls.tearDownClass = cls._HandleTearDownClass
+ cls._initialized = True
+
+ @classmethod
+ def _LogInfoBanner(cls, method_name, method_doc=None):
+ """Formats and logs test case information."""
+ logging.info('*' * BANNER_WIDTH)
+ logging.info(method_name.center(BANNER_WIDTH))
+ if method_doc:
+ for line in method_doc.split('\n'):
+ logging.info(line.center(BANNER_WIDTH))
+ logging.info('*' * BANNER_WIDTH)
+
+ @classmethod
+ def CreateTask(cls, *args, **kwargs):
+ """Convenience method to create a new task."""
+ task = task_controller.TaskController(*args, **kwargs)
+ cls._registration_server.RegisterTaskCallback(
+ task.otp, task.OnConnect)
+ return task
+
+ @classmethod
+ def _SetUpFramework(cls):
+ """Perform the framework-specific setup operations."""
+ cls._registration_server = (
+ task_registration_server.TaskRegistrationServer())
+ cls._registration_server.Start()
+
+ @classmethod
+ def _TearDownFramework(cls):
+ """Perform the framework-specific teardown operations."""
+ if cls._registration_server:
+ cls._registration_server.Shutdown()
+ task_controller.TaskController.ReleaseAllTasks()
+
+ @classmethod
+ def _HandleSetUpClass(cls):
+ """Performs common class-level setup operations.
+
+ This method performs test-wide setup such as starting the registration
+ server and then calls the original setUpClass method."""
+ try:
+ common_lib.InitLogging()
+ cls._LogInfoBanner('setUpClass', 'Performs class level setup.')
+ cls._SetUpFramework()
+ cls._OriginalSetUpClassMethod()
+ except:
+ # Make sure we tear down in case of any exceptions
+ cls._HandleTearDownClass(setup_failed=True)
+ exc_info = sys.exc_info()
+ logging.error('', exc_info=exc_info)
+ raise exc_info[0], exc_info[1], exc_info[2]
+
+ @classmethod
+ def _HandleTearDownClass(cls, setup_failed=False):
+ """Performs common class-level tear down operations.
+
+ This method calls the original tearDownClass then performs test-wide
+ tear down such as stopping the registration server.
+ """
+ cls._LogInfoBanner('tearDownClass', 'Performs class level tear down.')
+ try:
+ if not setup_failed:
+ cls._OriginalTearDownClassMethod()
+ finally:
+ cls._TearDownFramework()
+
+
+def main():
+ unittest.main(verbosity=0, argv=sys.argv[:1])
diff --git a/testing/legion/process.py b/testing/legion/process.py
new file mode 100644
index 0000000..356db61
--- /dev/null
+++ b/testing/legion/process.py
@@ -0,0 +1,247 @@
+# 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.
+
+"""RPC compatible subprocess-type module.
+
+This module defined both a task-side process class as well as a controller-side
+process wrapper for easier access and usage of the task-side process.
+"""
+
+import logging
+import subprocess
+import sys
+import threading
+
+#pylint: disable=relative-import
+import common_lib
+
+# Map swarming_client to use subprocess42
+sys.path.append(common_lib.SWARMING_DIR)
+
+from utils import subprocess42
+
+
+class ControllerProcessWrapper(object):
+ """Controller-side process wrapper class.
+
+ This class provides a more intuitive interface to task-side processes
+ than calling the methods directly using the RPC object.
+ """
+
+ def __init__(self, rpc, cmd, verbose=False, detached=False, cwd=None):
+ self._rpc = rpc
+ self._id = rpc.subprocess.Process(cmd)
+ if verbose:
+ self._rpc.subprocess.SetVerbose(self._id)
+ if detached:
+ self._rpc.subprocess.SetDetached(self._id)
+ if cwd:
+ self._rpc.subprocess.SetCwd(self._rpc, cwd)
+ self._rpc.subprocess.Start(self._id)
+
+ def Terminate(self):
+ logging.debug('Terminating process %s', self._id)
+ return self._rpc.subprocess.Terminate(self._id)
+
+ def Kill(self):
+ logging.debug('Killing process %s', self._id)
+ self._rpc.subprocess.Kill(self._id)
+
+ def Delete(self):
+ return self._rpc.subprocess.Delete(self._id)
+
+ def GetReturncode(self):
+ return self._rpc.subprocess.GetReturncode(self._id)
+
+ def ReadStdout(self):
+ """Returns all stdout since the last call to ReadStdout.
+
+ This call allows the user to read stdout while the process is running.
+ However each call will flush the local stdout buffer. In order to make
+ multiple calls to ReadStdout and to retain the entire output the results
+ of this call will need to be buffered in the calling code.
+ """
+ return self._rpc.subprocess.ReadStdout(self._id)
+
+ def ReadStderr(self):
+ """Returns all stderr read since the last call to ReadStderr.
+
+ See ReadStdout for additional details.
+ """
+ return self._rpc.subprocess.ReadStderr(self._id)
+
+ def ReadOutput(self):
+ """Returns the (stdout, stderr) since the last Read* call.
+
+ See ReadStdout for additional details.
+ """
+ return self._rpc.subprocess.ReadOutput(self._id)
+
+ def Wait(self):
+ return self._rpc.subprocess.Wait(self._id)
+
+ def Poll(self):
+ return self._rpc.subprocess.Poll(self._id)
+
+ def GetPid(self):
+ return self._rpc.subprocess.GetPid(self._id)
+
+
+
+class Process(object):
+ """Implements a task-side non-blocking subprocess.
+
+ This non-blocking subprocess allows the caller to continue operating while
+ also able to interact with this subprocess based on a key returned to
+ the caller at the time of creation.
+
+ Creation args are set via Set* methods called after calling Process but
+ before calling Start. This is due to a limitation of the XML-RPC
+ implementation not supporting keyword arguments.
+ """
+
+ _processes = {}
+ _process_next_id = 0
+ _creation_lock = threading.Lock()
+
+ def __init__(self, cmd):
+ self.stdout = ''
+ self.stderr = ''
+ self.cmd = cmd
+ self.proc = None
+ self.cwd = None
+ self.verbose = False
+ self.detached = False
+ self.data_lock = threading.Lock()
+
+ def __str__(self):
+ return '%r, cwd=%r, verbose=%r, detached=%r' % (
+ self.cmd, self.cwd, self.verbose, self.detached)
+
+ def _reader(self):
+ for pipe, data in self.proc.yield_any():
+ with self.data_lock:
+ if pipe == 'stdout':
+ self.stdout += data
+ if self.verbose:
+ sys.stdout.write(data)
+ else:
+ self.stderr += data
+ if self.verbose:
+ sys.stderr.write(data)
+
+ @classmethod
+ def KillAll(cls):
+ for key in cls._processes:
+ cls.Kill(key)
+
+ @classmethod
+ def Process(cls, cmd):
+ with cls._creation_lock:
+ key = 'Process%d' % cls._process_next_id
+ cls._process_next_id += 1
+ logging.debug('Creating process %s with cmd %r', key, cmd)
+ process = cls(cmd)
+ cls._processes[key] = process
+ return key
+
+ def _Start(self):
+ logging.info('Starting process %s', self)
+ self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE,
+ stderr=subprocess42.PIPE,
+ detached=self.detached, cwd=self.cwd)
+ threading.Thread(target=self._reader).start()
+
+ @classmethod
+ def Start(cls, key):
+ cls._processes[key]._Start()
+
+ @classmethod
+ def SetCwd(cls, key, cwd):
+ """Sets the process's cwd."""
+ logging.debug('Setting %s cwd to %s', key, cwd)
+ cls._processes[key].cwd = cwd
+
+ @classmethod
+ def SetDetached(cls, key):
+ """Creates a detached process."""
+ logging.debug('Setting %s.detached = True', key)
+ cls._processes[key].detached = True
+
+ @classmethod
+ def SetVerbose(cls, key):
+ """Sets the stdout and stderr to be emitted locally."""
+ logging.debug('Setting %s.verbose = True', key)
+ cls._processes[key].verbose = True
+
+ @classmethod
+ def Terminate(cls, key):
+ logging.debug('Terminating process %s', key)
+ cls._processes[key].proc.terminate()
+
+ @classmethod
+ def Kill(cls, key):
+ logging.debug('Killing process %s', key)
+ cls._processes[key].proc.kill()
+
+ @classmethod
+ def Delete(cls, key):
+ if cls.GetReturncode(key) is None:
+ logging.warning('Killing %s before deleting it', key)
+ cls.Kill(key)
+ logging.debug('Deleting process %s', key)
+ cls._processes.pop(key)
+
+ @classmethod
+ def GetReturncode(cls, key):
+ return cls._processes[key].proc.returncode
+
+ @classmethod
+ def ReadStdout(cls, key):
+ """Returns all stdout since the last call to ReadStdout.
+
+ This call allows the user to read stdout while the process is running.
+ However each call will flush the local stdout buffer. In order to make
+ multiple calls to ReadStdout and to retain the entire output the results
+ of this call will need to be buffered in the calling code.
+ """
+ proc = cls._processes[key]
+ with proc.data_lock:
+ # Perform a "read" on the stdout data
+ stdout = proc.stdout
+ proc.stdout = ''
+ return stdout
+
+ @classmethod
+ def ReadStderr(cls, key):
+ """Returns all stderr read since the last call to ReadStderr.
+
+ See ReadStdout for additional details.
+ """
+ proc = cls._processes[key]
+ with proc.data_lock:
+ # Perform a "read" on the stderr data
+ stderr = proc.stderr
+ proc.stderr = ''
+ return stderr
+
+ @classmethod
+ def ReadOutput(cls, key):
+ """Returns the (stdout, stderr) since the last Read* call.
+
+ See ReadStdout for additional details.
+ """
+ return cls.ReadStdout(key), cls.ReadStderr(key)
+
+ @classmethod
+ def Wait(cls, key):
+ return cls._processes[key].proc.wait()
+
+ @classmethod
+ def Poll(cls, key):
+ return cls._processes[key].proc.poll()
+
+ @classmethod
+ def GetPid(cls, key):
+ return cls._processes[key].proc.pid
diff --git a/testing/legion/rpc_methods.py b/testing/legion/rpc_methods.py
index 1a59f28..24d0312 100644
--- a/testing/legion/rpc_methods.py
+++ b/testing/legion/rpc_methods.py
@@ -4,18 +4,13 @@
"""Defines the task RPC methods."""
+import logging
import os
import sys
-import logging
import threading
#pylint: disable=relative-import
-import common_lib
-
-# Map swarming_client to use subprocess42
-sys.path.append(common_lib.SWARMING_DIR)
-
-from utils import subprocess42
+import process
class RPCMethods(object):
@@ -25,7 +20,7 @@
def __init__(self, server):
self._server = server
- self.subprocess = Subprocess
+ self.subprocess = process.Process
def _dispatch(self, method, params):
obj = self
@@ -54,161 +49,3 @@
"""
t = threading.Thread(target=self._server.shutdown)
t.start()
-
-
-class Subprocess(object):
- """Implements a server-based non-blocking subprocess.
-
- This non-blocking subprocess allows the caller to continue operating while
- also able to interact with this subprocess based on a key returned to
- the caller at the time of creation.
-
- Creation args are set via Set* methods called after calling Process but
- before calling Start. This is due to a limitation of the XML-RPC
- implementation not supporting keyword arguments.
- """
-
- _processes = {}
- _process_next_id = 0
- _creation_lock = threading.Lock()
-
- def __init__(self, cmd):
- self.stdout = ''
- self.stderr = ''
- self.cmd = cmd
- self.proc = None
- self.cwd = None
- self.verbose = False
- self.detached = False
- self.data_lock = threading.Lock()
-
- def __str__(self):
- return '%r, cwd=%r, verbose=%r, detached=%r' % (
- self.cmd, self.cwd, self.verbose, self.detached)
-
- def _reader(self):
- for pipe, data in self.proc.yield_any():
- with self.data_lock:
- if pipe == 'stdout':
- self.stdout += data
- if self.verbose:
- sys.stdout.write(data)
- else:
- self.stderr += data
- if self.verbose:
- sys.stderr.write(data)
-
- @classmethod
- def KillAll(cls):
- for key in cls._processes:
- cls.Kill(key)
-
- @classmethod
- def Process(cls, cmd):
- with cls._creation_lock:
- key = 'Process%d' % cls._process_next_id
- cls._process_next_id += 1
- logging.debug('Creating process %s', key)
- process = cls(cmd)
- cls._processes[key] = process
- return key
-
- def _Start(self):
- logging.info('Starting process %s', self)
- self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE,
- stderr=subprocess42.PIPE,
- detached=self.detached, cwd=self.cwd)
- threading.Thread(target=self._reader).start()
-
- @classmethod
- def Start(cls, key):
- cls._processes[key]._Start()
-
- @classmethod
- def SetCwd(cls, key, cwd):
- """Sets the process's cwd."""
- logging.debug('Setting %s cwd to %s', key, cwd)
- cls._processes[key].cwd = cwd
-
- @classmethod
- def SetDetached(cls, key):
- """Creates a detached process."""
- logging.debug('Setting %s to run detached', key)
- cls._processes[key].detached = True
-
- @classmethod
- def SetVerbose(cls, key):
- """Sets the stdout and stderr to be emitted locally."""
- logging.debug('Setting %s to be verbose', key)
- cls._processes[key].verbose = True
-
- @classmethod
- def Terminate(cls, key):
- logging.debug('Terminating process %s', key)
- cls._processes[key].proc.terminate()
-
- @classmethod
- def Kill(cls, key):
- logging.debug('Killing process %s', key)
- cls._processes[key].proc.kill()
-
- @classmethod
- def Delete(cls, key):
- if cls.GetReturncode(key) is None:
- logging.warning('Killing %s before deleting it', key)
- cls.Kill(key)
- logging.debug('Deleting process %s', key)
- cls._processes.pop(key)
-
- @classmethod
- def GetReturncode(cls, key):
- return cls._processes[key].proc.returncode
-
- @classmethod
- def ReadStdout(cls, key):
- """Returns all stdout since the last call to ReadStdout.
-
- This call allows the user to read stdout while the process is running.
- However each call will flush the local stdout buffer. In order to make
- multiple calls to ReadStdout and to retain the entire output the results
- of this call will need to be buffered in the calling code.
- """
- proc = cls._processes[key]
- with proc.data_lock:
- # Perform a "read" on the stdout data
- stdout = proc.stdout
- proc.stdout = ''
- return stdout
-
- @classmethod
- def ReadStderr(cls, key):
- """Returns all stderr read since the last call to ReadStderr.
-
- See ReadStdout for additional details.
- """
- proc = cls._processes[key]
- with proc.data_lock:
- # Perform a "read" on the stderr data
- stderr = proc.stderr
- proc.stderr = ''
- return stderr
-
- @classmethod
- def ReadOutput(cls, key):
- """Returns the (stdout, stderr) since the last Read* call.
-
- See ReadStdout for additional details.
- """
- return cls.ReadStdout(key), cls.ReadStderr(key)
-
- @classmethod
- def Wait(cls, key):
- return cls._processes[key].proc.wait()
-
- @classmethod
- def Poll(cls, key):
- return cls._processes[key].proc.poll()
-
- @classmethod
- def GetPid(cls, key):
- return cls._processes[key].proc.pid
diff --git a/testing/legion/task_controller.py b/testing/legion/task_controller.py
index df9ddbd..9514f44 100644
--- a/testing/legion/task_controller.py
+++ b/testing/legion/task_controller.py
@@ -17,6 +17,7 @@
#pylint: disable=relative-import
import common_lib
+import process
ISOLATE_PY = os.path.join(common_lib.SWARMING_DIR, 'isolate.py')
SWARMING_PY = os.path.join(common_lib.SWARMING_DIR, 'swarming.py')
@@ -125,6 +126,10 @@
for task in cls._tasks:
task.Release()
+ def Process(self, cmd, verbose=False, detached=False, cwd=None):
+ return process.ControllerProcessWrapper(
+ self.rpc, cmd, verbose, detached, cwd)
+
def _CreateOTP(self):
"""Creates the OTP."""
controller_name = socket.gethostname()
diff --git a/testing/legion/task_registration_server.py b/testing/legion/task_registration_server.py
index 52ba727..fe92dcd 100644
--- a/testing/legion/task_registration_server.py
+++ b/testing/legion/task_registration_server.py
@@ -39,7 +39,7 @@
def Start(self):
"""Starts the registration server."""
- logging.debug('Starting task registration server')
+ logging.info('Starting task registration server')
self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
(common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
allow_none=True, logRequests=False)
@@ -51,5 +51,5 @@
def Shutdown(self):
"""Shuts the discovery server down."""
if self._thread and self._thread.is_alive():
- logging.debug('Shutting down task registration server')
+ logging.info('Shutting down task registration server')
self._rpc_server.shutdown()
diff --git a/testing/scripts/gtest_perf_test.py b/testing/scripts/gtest_perf_test.py
index 6243a79..af4380f 100755
--- a/testing/scripts/gtest_perf_test.py
+++ b/testing/scripts/gtest_perf_test.py
@@ -11,6 +11,10 @@
import common
+def IsWindows():
+ return sys.platform == 'cygwin' or sys.platform.startswith('win')
+
+
def main_run(args):
filter_tests = []
if args.filter_file:
@@ -19,6 +23,8 @@
perf_id = args.properties.get('perf-id')
script_args = args.args
test_suite = script_args[0]
+ if IsWindows():
+ script_args[0] += '.exe'
with common.temporary_file() as tempfile_path:
gtest_args = [
diff --git a/testing/test.gni b/testing/test.gni
index 3afb9f7..ec56f01 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -67,7 +67,7 @@
}
deps = []
if (!defined(invoker.use_launcher) || invoker.use_launcher) {
- deps += [ "//testing/android:native_test_native_code" ]
+ deps += [ "//testing/android/native_test:native_test_native_code" ]
}
if (defined(invoker.deps)) {
deps += invoker.deps
diff --git a/testing/xvfb.py b/testing/xvfb.py
index ce53099..e7280f4 100755
--- a/testing/xvfb.py
+++ b/testing/xvfb.py
@@ -50,7 +50,7 @@
xvfb_path: Path to Xvfb.
"""
cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac',
- '-nolisten', 'tcp']
+ '-nolisten', 'tcp', '-dpi', '96']
try:
proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
diff --git a/third_party/junit/BUILD.gn b/third_party/junit/BUILD.gn
new file mode 100644
index 0000000..babe0f2
--- /dev/null
+++ b/third_party/junit/BUILD.gn
@@ -0,0 +1,20 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+# GYP: //third_party/junit.gyp:hamcrest_jar
+java_prebuilt("hamcrest") {
+ jar_path = "src/lib/hamcrest-core-1.1.jar"
+}
+
+# GYP: //third_party/junit.gyp:junit_jar
+java_library("junit") {
+ chromium_code = false
+ testonly = true
+ deps = [
+ ":hamcrest",
+ ]
+ DEPRECATED_java_in_dir = "src/src/main/java"
+}
diff --git a/third_party/junit/LICENSE b/third_party/junit/LICENSE
new file mode 100644
index 0000000..1aba77a
--- /dev/null
+++ b/third_party/junit/LICENSE
@@ -0,0 +1,218 @@
+JUnit
+
+Common Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial code and
+ documentation distributed under this Agreement, and
+ b) in the case of each subsequent Contributor:
+
+ i) changes to the Program, and
+
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates' from a
+Contributor if it was added to the Program by such Contributor itself or anyone
+acting on such Contributor's behalf. Contributions do not include additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are
+not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly perform,
+distribute and sublicense the Contribution of such Contributor, if any, and
+such derivative works, in source code and object code form.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under
+Licensed Patents to make, use, sell, offer to sell, import and otherwise
+transfer the Contribution of such Contributor, if any, in source code and
+object code form. This patent license shall apply to the combination of the
+Contribution and the Program if, at the time the Contribution is added by the
+Contributor, such addition of the Contribution causes such combination to be
+covered by the Licensed Patents. The patent license shall not apply to any
+other combinations which include the Contribution. No hardware per se is
+licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+licenses to its Contributions set forth herein, no assurances are provided by
+any Contributor that the Program does not infringe the patent or other
+intellectual property rights of any other entity. Each Contributor disclaims
+any liability to Recipient for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a condition to
+exercising the rights and licenses granted hereunder, each Recipient hereby
+assumes sole responsibility to secure any other intellectual property rights
+needed, if any. For example, if a third party patent license is required to
+allow Recipient to distribute the Program, it is Recipient's responsibility to
+acquire that license before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has sufficient
+copyright rights in its Contribution, if any, to grant the copyright license
+set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+
+ b) its license agreement:
+
+ i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose;
+
+ ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits;
+
+ iii) states that any provisions which differ from this Agreement are
+offered by that Contributor alone and not by any other party; and
+
+ iv) states that source code for the Program is available from such
+Contributor, and informs licensees how to obtain it in a reasonable manner on
+or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+
+ b) a copy of this Agreement must be included with each copy of the
+Program.
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its exercise
+of rights under this Agreement, including but not limited to the risks and
+costs of program errors, compliance with applicable laws, damage to or loss of
+data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with respect to
+a patent applicable to software (including a cross-claim or counterclaim in a
+lawsuit), then any patent licenses granted by that Contributor to such
+Recipient under this Agreement shall terminate as of the date such litigation
+is filed. In addition, if Recipient institutes patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's rights
+granted under Section 2(b) shall terminate as of the date such litigation is
+filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+IBM is the initial Agreement Steward. IBM may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial
+in any resulting litigation.
+
diff --git a/third_party/junit/OWNERS b/third_party/junit/OWNERS
new file mode 100644
index 0000000..212ffdf
--- /dev/null
+++ b/third_party/junit/OWNERS
@@ -0,0 +1,3 @@
+jbudorick@chromium.org
+klundberg@chromium.org
+
diff --git a/third_party/junit/README.chromium b/third_party/junit/README.chromium
new file mode 100644
index 0000000..5a1651b
--- /dev/null
+++ b/third_party/junit/README.chromium
@@ -0,0 +1,10 @@
+Name: JUnit
+URL: http://junit.org
+Version: 4.10
+License: Common Public License 1.0
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: JUnit is a java unit testing library.
+Local Modifications: None
+
diff --git a/third_party/junit/junit.gyp b/third_party/junit/junit.gyp
new file mode 100644
index 0000000..c797e06
--- /dev/null
+++ b/third_party/junit/junit.gyp
@@ -0,0 +1,34 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ # GN: //third_party/junit:hamcrest
+ 'target_name': 'hamcrest_jar',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'src/lib/hamcrest-core-1.1.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/junit:junit
+ 'target_name': 'junit_jar',
+ 'type': 'none',
+ 'dependencies': [
+ 'hamcrest_jar',
+ ],
+ 'variables': {
+ 'src_paths': [ 'src/src/main/java' ],
+ },
+ 'includes': [
+ '../../build/host_jar.gypi',
+ ],
+ },
+ ],
+}
+
diff --git a/third_party/libevent/event-config.h b/third_party/libevent/event-config.h
index 2e564db..c5c0e75 100644
--- a/third_party/libevent/event-config.h
+++ b/third_party/libevent/event-config.h
@@ -6,17 +6,17 @@
// event-config.h depending on your platform.
#if defined(__native_client_nonsfi__)
-#include "nacl_nonsfi/event-config.h"
+#include "third_party/libevent/nacl_nonsfi/event-config.h"
#elif defined(__APPLE__)
-#include "mac/event-config.h"
+#include "third_party/libevent/mac/event-config.h"
#elif defined(ANDROID)
-#include "android/event-config.h"
+#include "third_party/libevent/android/event-config.h"
#elif defined(__linux__)
-#include "linux/event-config.h"
+#include "third_party/libevent/linux/event-config.h"
#elif defined(__FreeBSD__)
-#include "freebsd/event-config.h"
+#include "third_party/libevent/freebsd/event-config.h"
#elif defined(__sun)
-#include "solaris/event-config.h"
+#include "third_party/libevent/solaris/event-config.h"
#else
#error generate event-config.h for your platform
#endif
diff --git a/third_party/libevent/libevent.gyp b/third_party/libevent/libevent.gyp
index a785d34..656dd63 100644
--- a/third_party/libevent/libevent.gyp
+++ b/third_party/libevent/libevent.gyp
@@ -27,6 +27,9 @@
'defines': [
'HAVE_CONFIG_H',
],
+ 'include_dirs': [
+ '../..',
+ ],
'conditions': [
# libevent has platform-specific implementation files. Since its
# native build uses autoconf, platform-specific config.h files are
diff --git a/third_party/libevent/libevent_nacl_nonsfi.gyp b/third_party/libevent/libevent_nacl_nonsfi.gyp
index 704de10..37a78ad 100644
--- a/third_party/libevent/libevent_nacl_nonsfi.gyp
+++ b/third_party/libevent/libevent_nacl_nonsfi.gyp
@@ -40,9 +40,6 @@
'build_pnacl_newlib': 0,
'build_nonsfi_helper': 1,
},
- 'dependencies': [
- '../../native_client/tools.gyp:prep_toolchain',
- ],
},
],
}],
diff --git a/third_party/libxml/DEPS b/third_party/libxml/DEPS
new file mode 100644
index 0000000..6dcfa15
--- /dev/null
+++ b/third_party/libxml/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ '+libxml',
+]
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index bfdff5b..f12d267 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -29,6 +29,7 @@
- Add helper classes in chromium/libxml_utils.cc and chromium/include/libxml/libxml_utils.h.
- Add a tweak to limit problems caused by excessive strings and buffers.
- Change the xmlNs struct a little bit, so it looks like it has no children
+- Prevent snprintf from being defined as _snprintf on VS 2015.
if treated as a generic xmlNode object.
- Fix pretty harmless use-after-free in generate-id function.
- Merge a clang warning fix http://git.gnome.org/browse/libxml2/commit/?id=713434d2309da469d64b35e163ea6556dadccada
diff --git a/third_party/libxml/patches/snprintf_config b/third_party/libxml/patches/snprintf_config
new file mode 100644
index 0000000..9d1ca62
--- /dev/null
+++ b/third_party/libxml/patches/snprintf_config
@@ -0,0 +1,14 @@
+diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h
+index 3fc9be5..5112ce6 100644
+--- a/third_party/libxml/win32/config.h
++++ b/third_party/libxml/win32/config.h
+@@ -95,7 +95,9 @@ static int isnan (double d) {
+
+ #if defined(_MSC_VER)
+ #define mkdir(p,m) _mkdir(p)
++#if _MSC_VER < 1900
+ #define snprintf _snprintf
++#endif
+ #if _MSC_VER < 1500
+ #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+ #endif
diff --git a/third_party/libxml/patches/snprintf_win32config b/third_party/libxml/patches/snprintf_win32config
new file mode 100644
index 0000000..3fec790
--- /dev/null
+++ b/third_party/libxml/patches/snprintf_win32config
@@ -0,0 +1,14 @@
+diff --git a/third_party/libxml/src/include/win32config.h b/third_party/libxml/src/include/win32config.h
+index 3fc9be5..5112ce6 100644
+--- a/third_party/libxml/src/include/win32config.h
++++ b/third_party/libxml/src/include/win32config.h
+@@ -95,7 +95,9 @@ static int isnan (double d) {
+
+ #if defined(_MSC_VER)
+ #define mkdir(p,m) _mkdir(p)
++#if _MSC_VER < 1900
+ #define snprintf _snprintf
++#endif
+ #if _MSC_VER < 1500
+ #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+ #endif
diff --git a/third_party/libxml/src/include/win32config.h b/third_party/libxml/src/include/win32config.h
index 3fc9be5..5112ce6 100644
--- a/third_party/libxml/src/include/win32config.h
+++ b/third_party/libxml/src/include/win32config.h
@@ -95,7 +95,9 @@
#if defined(_MSC_VER)
#define mkdir(p,m) _mkdir(p)
+#if _MSC_VER < 1900
#define snprintf _snprintf
+#endif
#if _MSC_VER < 1500
#define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
#endif
diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h
index 3fc9be5..5112ce6 100644
--- a/third_party/libxml/win32/config.h
+++ b/third_party/libxml/win32/config.h
@@ -95,7 +95,9 @@
#if defined(_MSC_VER)
#define mkdir(p,m) _mkdir(p)
+#if _MSC_VER < 1900
#define snprintf _snprintf
+#endif
#if _MSC_VER < 1500
#define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
#endif
diff --git a/third_party/mockito/BUILD.gn b/third_party/mockito/BUILD.gn
new file mode 100644
index 0000000..2f03b7c
--- /dev/null
+++ b/third_party/mockito/BUILD.gn
@@ -0,0 +1,28 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+# GYP: //third_party/mockito.gyp:cglib_and_asm_jar
+java_prebuilt("cglib_and_asm_java") {
+ jar_path = "src/lib/repackaged/cglib-and-asm-1.0.jar"
+}
+
+# GYP: //third_party/mockito.gyp:objenesis_jar
+java_prebuilt("objenesis_java") {
+ jar_path = "src/lib/run/objenesis-2.1.jar"
+}
+
+# GYP: //third_party/mockito.gyp:mockito_jar
+java_library("mockito_java") {
+ chromium_code = false
+ testonly = true
+ deps = [
+ ":cglib_and_asm_java",
+ ":objenesis_java",
+ "../junit:junit",
+ "../junit:hamcrest",
+ ]
+ DEPRECATED_java_in_dir = "src/src"
+}
diff --git a/third_party/mockito/LICENSE b/third_party/mockito/LICENSE
new file mode 100644
index 0000000..5a311f7
--- /dev/null
+++ b/third_party/mockito/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/mockito/OWNERS b/third_party/mockito/OWNERS
new file mode 100644
index 0000000..bd675fb
--- /dev/null
+++ b/third_party/mockito/OWNERS
@@ -0,0 +1,2 @@
+jbudorick@chromium.org
+klundberg@chromium.org
diff --git a/third_party/mockito/README.chromium b/third_party/mockito/README.chromium
new file mode 100644
index 0000000..1d932ad
--- /dev/null
+++ b/third_party/mockito/README.chromium
@@ -0,0 +1,9 @@
+Name: Mockito
+URL: https://code.google.com/p/mockito
+Version: 1.10.5
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: Mockito is a java mocking framework.
+Local Modifications: None
diff --git a/third_party/mockito/mockito.gyp b/third_party/mockito/mockito.gyp
new file mode 100644
index 0000000..d9a9db2
--- /dev/null
+++ b/third_party/mockito/mockito.gyp
@@ -0,0 +1,47 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ # GN: //third_party/mockito:cglib_and_asm_java
+ 'target_name': 'cglib_and_asm_jar',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'src/lib/repackaged/cglib-and-asm-1.0.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/mockito:objenesis_java
+ 'target_name': 'objenesis_jar',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'src/lib/run/objenesis-2.1.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/mockito:mockito_java
+ 'target_name': 'mockito_jar',
+ 'type': 'none',
+ 'dependencies': [
+ 'cglib_and_asm_jar',
+ 'objenesis_jar',
+ '../junit/junit.gyp:junit_jar',
+ ],
+ 'variables': {
+ 'src_paths': [ 'src/src' ],
+ },
+ 'includes': [
+ '../../build/host_jar.gypi',
+ ],
+ },
+ ],
+}
+
diff --git a/third_party/modp_b64/DEPS b/third_party/modp_b64/DEPS
new file mode 100644
index 0000000..8061b5a
--- /dev/null
+++ b/third_party/modp_b64/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ '+build',
+]
\ No newline at end of file
diff --git a/third_party/modp_b64/modp_b64_nacl.gyp b/third_party/modp_b64/modp_b64_nacl.gyp
index cd0d210..e2f4a25 100644
--- a/third_party/modp_b64/modp_b64_nacl.gyp
+++ b/third_party/modp_b64/modp_b64_nacl.gyp
@@ -16,9 +16,6 @@
'build_newlib': 1,
'build_pnacl_newlib': 1,
},
- 'dependencies': [
- '<(DEPTH)/native_client/tools.gyp:prep_toolchain',
- ],
'sources': [
'modp_b64.cc',
'modp_b64.h',
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn
new file mode 100644
index 0000000..211c3d6
--- /dev/null
+++ b/third_party/robolectric/BUILD.gn
@@ -0,0 +1,31 @@
+# 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("//build/config/android/rules.gni")
+
+# GYP: //third_party/robolectric/robolectric.gyp:android-all-4.3_r2-robolectric-0
+java_prebuilt("android-all-4.3_r2-robolectric-0") {
+ jar_path = "lib/android-all-4.3_r2-robolectric-0.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:tagsoup-1.2
+java_prebuilt("tagsoup-1.2") {
+ jar_path = "lib/tagsoup-1.2.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:json-20080701
+java_prebuilt("json-20080701") {
+ jar_path = "lib/json-20080701.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:robolectric_jar
+java_prebuilt("robolectric_java") {
+ testonly = true
+ jar_path = "lib/robolectric-2.4-jar-with-dependencies.jar"
+ deps = [
+ ":android-all-4.3_r2-robolectric-0",
+ ":tagsoup-1.2",
+ ":json-20080701",
+ ]
+}
diff --git a/third_party/robolectric/LICENSE b/third_party/robolectric/LICENSE
new file mode 100644
index 0000000..f433b1a
--- /dev/null
+++ b/third_party/robolectric/LICENSE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/third_party/robolectric/OWNERS b/third_party/robolectric/OWNERS
new file mode 100644
index 0000000..bd675fb
--- /dev/null
+++ b/third_party/robolectric/OWNERS
@@ -0,0 +1,2 @@
+jbudorick@chromium.org
+klundberg@chromium.org
diff --git a/third_party/robolectric/README.chromium b/third_party/robolectric/README.chromium
new file mode 100644
index 0000000..10aeba3
--- /dev/null
+++ b/third_party/robolectric/README.chromium
@@ -0,0 +1,11 @@
+Name: Robolectric
+URL: http://robolectric.org
+Version: 2.4
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: Robolectric is a unit test framework for Android. To update the
+robolectric jars, go to robolectric.org/download and follow link to
+robolectric-X.X.X-jar-with-dependencies.jar.
+Local Modifications: None
diff --git a/third_party/robolectric/lib b/third_party/robolectric/lib
new file mode 160000
index 0000000..6b63c99
--- /dev/null
+++ b/third_party/robolectric/lib
@@ -0,0 +1 @@
+Subproject commit 6b63c99a8b6967acdb42cbed0adb067c80efc810
diff --git a/third_party/robolectric/licenses/extreme.indiana.edu.license.txt b/third_party/robolectric/licenses/extreme.indiana.edu.license.txt
new file mode 100644
index 0000000..c743155
--- /dev/null
+++ b/third_party/robolectric/licenses/extreme.indiana.edu.license.txt
@@ -0,0 +1,47 @@
+Indiana University Extreme! Lab Software License
+
+Version 1.1.1
+
+Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+3. The end-user documentation included with the redistribution, if any,
+ must include the following acknowledgment:
+
+ "This product includes software developed by the Indiana University
+ Extreme! Lab (http://www.extreme.indiana.edu/)."
+
+Alternately, this acknowledgment may appear in the software itself,
+if and wherever such third-party acknowledgments normally appear.
+
+4. The names "Indiana Univeristy" and "Indiana Univeristy Extreme! Lab"
+must not be used to endorse or promote products derived from this
+software without prior written permission. For written permission,
+please contact http://www.extreme.indiana.edu/.
+
+5. Products derived from this software may not use "Indiana Univeristy"
+name nor may "Indiana Univeristy" appear in their name, without prior
+written permission of the Indiana University.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHORS, COPYRIGHT HOLDERS OR ITS CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/third_party/robolectric/licenses/javolution.license.txt b/third_party/robolectric/licenses/javolution.license.txt
new file mode 100644
index 0000000..0633749
--- /dev/null
+++ b/third_party/robolectric/licenses/javolution.license.txt
@@ -0,0 +1,23 @@
+Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+Copyright (c) 2006, Javolution (http://javolution.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/robolectric/licenses/pivotal.labs.license.txt b/third_party/robolectric/licenses/pivotal.labs.license.txt
new file mode 100644
index 0000000..c9dccb8
--- /dev/null
+++ b/third_party/robolectric/licenses/pivotal.labs.license.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010 Xtreme Labs and Pivotal Labs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/robolectric/robolectric.gyp b/third_party/robolectric/robolectric.gyp
new file mode 100644
index 0000000..7c3d785
--- /dev/null
+++ b/third_party/robolectric/robolectric.gyp
@@ -0,0 +1,58 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ # GN: //third_party/robolectric:android-all-4.3_r2-robolectric-0
+ 'target_name': 'android-all-4.3_r2-robolectric-0',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'lib/android-all-4.3_r2-robolectric-0.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/robolectric:tagsoup-1.2
+ 'target_name': 'tagsoup-1.2',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'lib/tagsoup-1.2.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/robolectric:json-20080701
+ 'target_name': 'json-20080701',
+ 'type': 'none',
+ 'variables': {
+ 'jar_path': 'lib/json-20080701.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ {
+ # GN: //third_party/robolectric:robolectric_java
+ 'target_name': 'robolectric_jar',
+ 'type': 'none',
+ 'dependencies': [
+ 'android-all-4.3_r2-robolectric-0',
+ 'tagsoup-1.2',
+ 'json-20080701',
+ ],
+ 'variables': {
+ 'jar_path': 'lib/robolectric-2.4-jar-with-dependencies.jar',
+ },
+ 'includes': [
+ '../../build/host_prebuilt_jar.gypi',
+ ]
+ },
+ ],
+}
+
diff --git a/third_party/tcmalloc/DEPS b/third_party/tcmalloc/DEPS
new file mode 100644
index 0000000..b0a0897
--- /dev/null
+++ b/third_party/tcmalloc/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ '+base',
+ '+build',
+ '+gperftools',
+ '+tests',
+ '+../config.h',
+]
diff --git a/third_party/tcmalloc/vendor/packages/deb.sh b/third_party/tcmalloc/vendor/packages/deb.sh
deleted file mode 100644
index 31b423c..0000000
--- a/third_party/tcmalloc/vendor/packages/deb.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash -e
-
-# This takes one commandline argument, the name of the package. If no
-# name is given, then we'll end up just using the name associated with
-# an arbitrary .tar.gz file in the rootdir. That's fine: there's probably
-# only one.
-#
-# Run this from the 'packages' directory, just under rootdir
-
-## Set LIB to lib if exporting a library, empty-string else
-LIB=
-#LIB=lib
-
-PACKAGE="$1"
-VERSION="$2"
-
-# We can only build Debian packages, if the Debian build tools are installed
-if [ \! -x /usr/bin/debuild ]; then
- echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2
- exit 0
-fi
-
-# Double-check we're in the packages directory, just under rootdir
-if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then
- echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
- echo "Also, you must run \"make dist\" before running this script." 1>&2
- exit 0
-fi
-
-# Find the top directory for this package
-topdir="${PWD%/*}"
-
-# Find the tar archive built by "make dist"
-archive="${PACKAGE}-${VERSION}"
-archive_with_underscore="${PACKAGE}_${VERSION}"
-if [ -z "${archive}" ]; then
- echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2
- exit 0
-fi
-
-# Create a pristine directory for building the Debian package files
-trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM
-
-rm -rf tmp
-mkdir -p tmp
-cd tmp
-
-# Debian has very specific requirements about the naming of build
-# directories, and tar archives. It also wants to write all generated
-# packages to the parent of the source directory. We accommodate these
-# requirements by building directly from the tar file.
-ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz"
-# Some version of debuilder want foo.orig.tar.gz with _ between versions.
-ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive_with_underscore}.orig.tar.gz"
-tar zfx "${LIB}${archive}.orig.tar.gz"
-[ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}"
-cd "${LIB}${archive}"
-# This is one of those 'specific requirements': where the deb control files live
-cp -a "packages/deb" "debian"
-
-# Now, we can call Debian's standard build tool
-debuild -uc -us
-cd ../.. # get back to the original top-level dir
-
-# We'll put the result in a subdirectory that's named after the OS version
-# we've made this .deb file for.
-destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)"
-
-rm -rf "$destdir"
-mkdir -p "$destdir"
-mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir"
-
-echo
-echo "The Debian package files are located in $PWD/$destdir"
diff --git a/third_party/tcmalloc/vendor/packages/deb/README b/third_party/tcmalloc/vendor/packages/deb/README
deleted file mode 100644
index 57becfd..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/README
+++ /dev/null
@@ -1,7 +0,0 @@
-The list of files here isn't complete. For a step-by-step guide on
-how to set this package up correctly, check out
- http://www.debian.org/doc/maint-guide/
-
-Most of the files that are in this directory are boilerplate.
-However, you may need to change the list of binary-arch dependencies
-in 'rules'.
diff --git a/third_party/tcmalloc/vendor/packages/deb/changelog b/third_party/tcmalloc/vendor/packages/deb/changelog
deleted file mode 100644
index dad1d5f..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/changelog
+++ /dev/null
@@ -1,196 +0,0 @@
-gperftools (2.0-1) unstable; urgency=low
-
- * New upstream release.
- * Package renamed from google-perftools to gperftools.
-
- -- Google Inc. and others <google-perftools@googlegroups.com> Fri, 03 Feb 2012 15:40:45 -0800
-
-google-perftools (1.10-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 31 Jan 2012 10:43:50 -0800
-
-google-perftools (1.9-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 22 Dec 2011 16:22:45 -0800
-
-google-perftools (1.8-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 15 Jul 2011 16:10:51 -0700
-
-google-perftools (1.7-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 04 Feb 2011 15:54:31 -0800
-
-google-perftools (1.6-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 05 Aug 2010 12:48:03 -0700
-
-google-perftools (1.5-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 19 Jan 2010 14:46:12 -0800
-
-google-perftools (1.4-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 10 Sep 2009 13:51:15 -0700
-
-google-perftools (1.3-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 09 Jun 2009 18:19:06 -0700
-
-google-perftools (1.2-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 17 Apr 2009 16:40:48 -0700
-
-google-perftools (1.1-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Wed, 11 Mar 2009 11:25:34 -0700
-
-google-perftools (1.0-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 06 Jan 2009 13:58:56 -0800
-
-google-perftools (1.0rc1-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 11 Dec 2008 16:01:32 -0800
-
-google-perftools (0.99.1-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Sat, 20 Sep 2008 09:37:18 -0700
-
-google-perftools (0.99-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 18 Sep 2008 16:00:27 -0700
-
-google-perftools (0.98-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Mon, 09 Jun 2008 16:47:03 -0700
-
-google-perftools (0.97-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Mon, 21 Apr 2008 15:20:52 -0700
-
-google-perftools (0.96-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 18 Mar 2008 14:30:44 -0700
-
-google-perftools (0.95-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 12 Feb 2008 12:28:32 -0800
-
-google-perftools (0.94-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 29 Nov 2007 07:59:43 -0800
-
-google-perftools (0.93-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 17 Aug 2007 12:32:56 -0700
-
-google-perftools (0.92-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 17 Jul 2007 22:26:27 -0700
-
-google-perftools (0.91-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Wed, 18 Apr 2007 16:43:55 -0700
-
-google-perftools (0.90-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 13 Apr 2007 14:50:51 -0700
-
-google-perftools (0.8-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Wed, 14 Jun 2006 15:11:14 -0700
-
-google-perftools (0.7-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Thu, 13 Apr 2006 20:59:09 -0700
-
-google-perftools (0.6-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 27 Jan 2006 14:04:27 -0800
-
-google-perftools (0.5-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Mon, Nov 14 17:28:59 2005 -0800
-
-google-perftools (0.4-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Wed, 26 Oct 2005 15:19:16 -0700
-
-google-perftools (0.3-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Fri, 24 Jun 2005 18:02:26 -0700
-
-google-perftools (0.2-1) unstable; urgency=low
-
- * New upstream release.
-
- -- Google Inc. <opensource@google.com> Tue, 31 May 2005 08:14:38 -0700
-
-google-perftools (0.1-1) unstable; urgency=low
-
- * Initial release.
- The google-perftools package contains some utilities to improve
- and analyze the performance of C++ programs. This includes an
- optimized thread-caching malloc() and cpu and heap profiling
- utilities.
-
- -- Google Inc. <opensource@google.com> Fri, 11 Mar 2005 08:07:33 -0800
diff --git a/third_party/tcmalloc/vendor/packages/deb/compat b/third_party/tcmalloc/vendor/packages/deb/compat
deleted file mode 100644
index b8626c4..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/compat
+++ /dev/null
@@ -1 +0,0 @@
-4
diff --git a/third_party/tcmalloc/vendor/packages/deb/control b/third_party/tcmalloc/vendor/packages/deb/control
deleted file mode 100644
index a553594..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/control
+++ /dev/null
@@ -1,25 +0,0 @@
-Source: gperftools
-Priority: optional
-Maintainer: Google Inc. and others <google-perftools@googlegroups.com>
-Build-Depends: debhelper (>= 4.0.0), binutils
-Standards-Version: 3.6.1
-
-Package: libgperftools-dev
-Section: libdevel
-Architecture: any
-Depends: libgperftools0 (= ${Source-Version})
-Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
- The gperftools package contains some utilities to improve and
- analyze the performance of C++ programs. This includes an optimized
- thread-caching malloc() and cpu and heap profiling utilities. The
- devel package contains static and debug libraries and header files
- for developing applications that use the gperftools package.
-
-Package: libgperftools0
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}
-Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
- The gperftools package contains some utilities to improve and
- analyze the performance of C++ programs. This includes an optimized
- thread-caching malloc() and cpu and heap profiling utilities.
diff --git a/third_party/tcmalloc/vendor/packages/deb/copyright b/third_party/tcmalloc/vendor/packages/deb/copyright
deleted file mode 100644
index 1a11eb7..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/copyright
+++ /dev/null
@@ -1,35 +0,0 @@
-This package was debianized by Craig Silverstein <google-perftools@googlegroups.com>
-on Fri, 03 Feb 2012 15:40:45 -0800.
-
-It was downloaded from http://code.google.com/p/gperftools/downloads/list
-
-Upstream Author: google-perftools@googlegroups.com
-
-Copyright (c) 2005, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/tcmalloc/vendor/packages/deb/docs b/third_party/tcmalloc/vendor/packages/deb/docs
deleted file mode 100644
index df891c9..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/docs
+++ /dev/null
@@ -1,47 +0,0 @@
-AUTHORS
-COPYING
-ChangeLog
-INSTALL
-NEWS
-README
-TODO
-doc/cpuprofile.html
-doc/cpuprofile-fileformat.html
-doc/designstyle.css
-doc/heap-example1.png
-doc/heap_checker.html
-doc/heapprofile.html
-doc/index.html
-doc/overview.gif
-doc/pageheap.gif
-doc/pprof-test-big.gif
-doc/pprof-test.gif
-doc/pprof-vsnprintf-big.gif
-doc/pprof-vsnprintf.gif
-doc/pprof.1
-doc/pprof_remote_servers.html
-doc/spanmap.gif
-doc/t-test1.times.txt
-doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
-doc/tcmalloc-opspersec.vs.size.1.threads.png
-doc/tcmalloc-opspersec.vs.size.12.threads.png
-doc/tcmalloc-opspersec.vs.size.16.threads.png
-doc/tcmalloc-opspersec.vs.size.2.threads.png
-doc/tcmalloc-opspersec.vs.size.20.threads.png
-doc/tcmalloc-opspersec.vs.size.3.threads.png
-doc/tcmalloc-opspersec.vs.size.4.threads.png
-doc/tcmalloc-opspersec.vs.size.5.threads.png
-doc/tcmalloc-opspersec.vs.size.8.threads.png
-doc/tcmalloc.html
-doc/threadheap.gif
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
deleted file mode 100644
index 8f88347..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
+++ /dev/null
@@ -1,5 +0,0 @@
-usr/lib
-usr/lib/pkgconfig
-usr/include
-usr/include/google
-usr/include/gperftools
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
deleted file mode 100644
index e863529..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
+++ /dev/null
@@ -1,12 +0,0 @@
-usr/include/google/*
-usr/include/gperftools/*
-usr/lib/lib*.so
-usr/lib/lib*.a
-usr/lib/*.la
-usr/lib/pkgconfig/*.pc
-debian/tmp/usr/include/google/*
-debian/tmp/usr/include/gperftools/*
-debian/tmp/usr/lib/lib*.so
-debian/tmp/usr/lib/lib*.a
-debian/tmp/usr/lib/*.la
-debian/tmp/usr/lib/pkgconfig/*.pc
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
deleted file mode 100644
index 14f5b95..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib
-usr/bin
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
deleted file mode 100644
index 047eed5..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
+++ /dev/null
@@ -1,4 +0,0 @@
-usr/lib/lib*.so.*
-usr/bin/pprof*
-debian/tmp/usr/lib/lib*.so.*
-debian/tmp/usr/bin/pprof*
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
deleted file mode 100644
index 08d1476..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
+++ /dev/null
@@ -1 +0,0 @@
-doc/pprof.1
diff --git a/third_party/tcmalloc/vendor/packages/deb/rules b/third_party/tcmalloc/vendor/packages/deb/rules
deleted file mode 100644
index f520bef..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/rules
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
- CFLAGS += -O0
-else
- CFLAGS += -O2
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
- INSTALL_PROGRAM += -s
-endif
-
-# shared library versions, option 1
-#version=2.0.5
-#major=2
-# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
-version=`ls src/.libs/lib*.so.* | \
- awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
-major=`ls src/.libs/lib*.so.* | \
- awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
-
-config.status: configure
- dh_testdir
- # Add here commands to configure the package.
- CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
-
-
-build: build-stamp
-build-stamp: config.status
- dh_testdir
-
- # Add here commands to compile the package.
- $(MAKE)
-
- touch build-stamp
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp
-
- # Add here commands to clean up after the build process.
- -$(MAKE) distclean
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
- cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
- cp -f /usr/share/misc/config.guess config.guess
-endif
-
-
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_clean -k
- dh_installdirs
-
- # Add here commands to install the package into debian/tmp
- $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs ChangeLog
- dh_installdocs
- dh_installexamples
- dh_install --sourcedir=debian/tmp
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_installinit
-# dh_installcron
-# dh_installinfo
- dh_installman
- dh_link
- dh_strip
- dh_compress
- dh_fixperms
-# dh_perl
-# dh_python
- dh_makeshlibs
- dh_installdeb
- dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/third_party/tcmalloc/vendor/packages/rpm.sh b/third_party/tcmalloc/vendor/packages/rpm.sh
deleted file mode 100644
index 448a032..0000000
--- a/third_party/tcmalloc/vendor/packages/rpm.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/sh -e
-
-# Run this from the 'packages' directory, just under rootdir
-
-# We can only build rpm packages, if the rpm build tools are installed
-if [ \! -x /usr/bin/rpmbuild ]
-then
- echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2
- exit 0
-fi
-
-# Check the commandline flags
-PACKAGE="$1"
-VERSION="$2"
-fullname="${PACKAGE}-${VERSION}"
-archive=../$fullname.tar.gz
-
-if [ -z "$1" -o -z "$2" ]
-then
- echo "Usage: $0 <package name> <package version>" 1>&2
- exit 0
-fi
-
-# Double-check we're in the packages directory, just under rootdir
-if [ \! -r ../Makefile -a \! -r ../INSTALL ]
-then
- echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
- echo "Also, you must run \"make dist\" before running this script." 1>&2
- exit 0
-fi
-
-if [ \! -r "$archive" ]
-then
- echo "Cannot find $archive. Run \"make dist\" first." 1>&2
- exit 0
-fi
-
-# Create the directory where the input lives, and where the output should live
-RPM_SOURCE_DIR="/tmp/rpmsource-$fullname"
-RPM_BUILD_DIR="/tmp/rpmbuild-$fullname"
-
-trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM
-
-rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR"
-mkdir "$RPM_SOURCE_DIR"
-mkdir "$RPM_BUILD_DIR"
-
-cp "$archive" "$RPM_SOURCE_DIR"
-
-# rpmbuild -- as far as I can tell -- asks the OS what CPU it has.
-# This may differ from what kind of binaries gcc produces. dpkg
-# does a better job of this, so if we can run 'dpkg --print-architecture'
-# to get the build CPU, we use that in preference of the rpmbuild
-# default.
-target=`dpkg --print-architecture 2>/dev/null || echo ""`
-if [ -n "$target" ]
-then
- target=" --target $target"
-fi
-
-rpmbuild -bb rpm/rpm.spec $target \
- --define "NAME $PACKAGE" \
- --define "VERSION $VERSION" \
- --define "_sourcedir $RPM_SOURCE_DIR" \
- --define "_builddir $RPM_BUILD_DIR" \
- --define "_rpmdir $RPM_SOURCE_DIR"
-
-# We put the output in a directory based on what system we've built for
-destdir=rpm-unknown
-if [ -r /etc/issue ]
-then
- grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7
- grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8
- grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9
- grep "Fedora Core.*release 1" /etc/issue >/dev/null 2>&1 && destdir=fc1
- grep "Fedora Core.*release 2" /etc/issue >/dev/null 2>&1 && destdir=fc2
- grep "Fedora Core.*release 3" /etc/issue >/dev/null 2>&1 && destdir=fc3
-fi
-
-rm -rf "$destdir"
-mkdir -p "$destdir"
-# We want to get not only the main package but devel etc, hence the middle *
-mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir"
-
-echo
-echo "The rpm package file(s) are located in $PWD/$destdir"
diff --git a/third_party/tcmalloc/vendor/packages/rpm/rpm.spec b/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
deleted file mode 100644
index bb9a4ee..0000000
--- a/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
+++ /dev/null
@@ -1,77 +0,0 @@
-%define RELEASE 1
-%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
-%define prefix /usr
-
-Name: %NAME
-Summary: Performance tools for C++
-Version: %VERSION
-Release: %rel
-Group: Development/Libraries
-URL: http://code.google.com/p/gperftools/
-License: BSD
-Vendor: Google Inc. and others
-Packager: Google Inc. and others <google-perftools@googlegroups.com>
-Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz
-Distribution: Redhat 7 and above.
-Buildroot: %{_tmppath}/%{name}-root
-Prefix: %prefix
-
-%description
-The %name packages contains some utilities to improve and analyze the
-performance of C++ programs. This includes an optimized thread-caching
-malloc() and cpu and heap profiling utilities.
-
-%package devel
-Summary: Performance tools for C++
-Group: Development/Libraries
-Requires: %{NAME} = %{VERSION}
-
-%description devel
-The %name-devel package contains static and debug libraries and header
-files for developing applications that use the %name package.
-
-%changelog
- * Mon Apr 20 2009 <opensource@google.com>
- - Change build rule to use a configure line more like '%configure'
- - Change install to use DESTDIR instead of prefix for configure
- - Use wildcards for doc/ and lib/ directories
-
- * Fri Mar 11 2005 <opensource@google.com>
- - First draft
-
-%prep
-%setup
-
-%build
-# I can't use '% configure', because it defines -m32 which breaks some
-# of the low-level atomicops files in this package. But I do take
-# as much from % configure (in /usr/lib/rpm/macros) as I can.
-./configure --prefix=%{_prefix} --exec-prefix=%{_exec_prefix} --bindir=%{_bindir} --sbindir=%{_sbindir} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --libexecdir=%{_libexecdir} --localstatedir=%{_localstatedir} --sharedstatedir=%{_sharedstatedir} --mandir=%{_mandir} --infodir=%{_infodir}
-make
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make DESTDIR=$RPM_BUILD_ROOT install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-
-%docdir %{prefix}/share/doc/%{NAME}-%{VERSION}
-%{prefix}/share/doc/%{NAME}-%{VERSION}/*
-
-%{_libdir}/*.so.*
-%{_bindir}/pprof
-%{_mandir}/man1/pprof.1*
-
-%files devel
-%defattr(-,root,root)
-
-%{_includedir}/google
-%{_includedir}/gperftools
-%{_libdir}/*.a
-%{_libdir}/*.la
-%{_libdir}/*.so
-%{_libdir}/pkgconfig/*.pc
diff --git a/tools/android/checkstyle/checkstyle.py b/tools/android/checkstyle/checkstyle.py
index 99a9fc9..44e1ecf 100644
--- a/tools/android/checkstyle/checkstyle.py
+++ b/tools/android/checkstyle/checkstyle.py
@@ -13,7 +13,7 @@
os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir))
CHECKSTYLE_ROOT = os.path.join(CHROMIUM_SRC, 'third_party', 'checkstyle',
- 'checkstyle-6.1-all.jar')
+ 'checkstyle-6.5-all.jar')
def RunCheckstyle(input_api, output_api, style_file, black_list=None):
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index c43f779..9e56dd9 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -101,8 +101,10 @@
<property name="severity" value="error"/>
</module>
<module name="NeedBraces">
- <property name="severity" value="info"/>
- <property name="tokens" value="LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
+ <message key="needBraces" value="if, for, while, and do require curly braces unless they are single-line statements."/>
+ <property name="severity" value="error"/>
+ <property name="tokens" value="LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, LITERAL_IF"/>
+ <property name="allowSingleLineStatement" value="true"/>
</module>
<module name="EmptyBlock">
<property name="severity" value="error"/>
diff --git a/tools/android/findbugs_plugin/findbugs.xml b/tools/android/findbugs_plugin/findbugs.xml
index 43b1f34..a1c4b5e 100644
--- a/tools/android/findbugs_plugin/findbugs.xml
+++ b/tools/android/findbugs_plugin/findbugs.xml
@@ -11,8 +11,8 @@
provider="chromium"
website="http://code.google.com/p/chromium/wiki/UseFindBugsForAndroid">
<Detector class="org.chromium.tools.findbugs.plugin.SynchronizedThisDetector" reports="CHROMIUM_SYNCHRONIZED_THIS" />
- <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS" abbrev="CST" category="CORRECTNESS"/>
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS" abbrev="CHROMIUM" category="CORRECTNESS"/>
<Detector class="org.chromium.tools.findbugs.plugin.SynchronizedMethodDetector" reports="CHROMIUM_SYNCHRONIZED_METHOD" />
- <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD" abbrev="CSM" category="CORRECTNESS"/>
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD" abbrev="CHROMIUM" category="CORRECTNESS"/>
</FindbugsPlugin>
diff --git a/tools/android/findbugs_plugin/findbugs_plugin.gyp b/tools/android/findbugs_plugin/findbugs_plugin.gyp
index 16d06e6..440d779 100644
--- a/tools/android/findbugs_plugin/findbugs_plugin.gyp
+++ b/tools/android/findbugs_plugin/findbugs_plugin.gyp
@@ -9,6 +9,7 @@
'type': 'none',
'variables': {
'java_in_dir': 'test/java/',
+ 'run_findbugs': 0,
},
'includes': [ '../../../build/java.gypi' ],
}
diff --git a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar b/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
index 6ccf61b..451566d 100644
--- a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
+++ b/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
Binary files differ
diff --git a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py b/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
index a570cdb..e36fe8e 100755
--- a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
+++ b/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
@@ -14,7 +14,7 @@
# remove the expected result of exsting tests.
-import optparse
+import argparse
import os
import sys
@@ -26,28 +26,79 @@
from pylib.utils import findbugs
+_EXPECTED_WARNINGS = set([
+ findbugs.FindBugsWarning(
+ bug_type='CHROMIUM_SYNCHRONIZED_THIS',
+ start_line=15,
+ end_line=15,
+ file_name='SimpleSynchronizedThis.java',
+ message=(
+ "Shouldn't use synchronized(this)",
+ 'In class org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedThis',
+ 'In method org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedThis.synchronizedThis()',
+ 'At SimpleSynchronizedThis.java:[line 15]',
+ )),
+ findbugs.FindBugsWarning(
+ bug_type='CHROMIUM_SYNCHRONIZED_METHOD',
+ start_line=14,
+ end_line=14,
+ file_name='SimpleSynchronizedStaticMethod.java',
+ message=(
+ "Shouldn't use synchronized method",
+ 'In class org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedStaticMethod',
+ 'In method org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedStaticMethod.synchronizedStaticMethod()',
+ 'At SimpleSynchronizedStaticMethod.java:[line 14]',
+ )),
+ findbugs.FindBugsWarning(
+ bug_type='CHROMIUM_SYNCHRONIZED_METHOD',
+ start_line=15,
+ end_line=15,
+ file_name='SimpleSynchronizedMethod.java',
+ message=(
+ "Shouldn't use synchronized method",
+ 'In class org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedMethod',
+ 'In method org.chromium.tools.findbugs.plugin.'
+ + 'SimpleSynchronizedMethod.synchronizedMethod()',
+ 'At SimpleSynchronizedMethod.java:[line 15]',
+ )),
+])
+
+
def main(argv):
- parser = findbugs.GetCommonParser()
- options, _ = parser.parse_args()
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-l', '--release-build', action='store_true', dest='release',
+ help='Run the release build of the findbugs plugin test.')
+ args = parser.parse_args()
- if not options.known_bugs:
- options.known_bugs = os.path.join(constants.DIR_SOURCE_ROOT, 'tools',
- 'android', 'findbugs_plugin', 'test',
- 'expected_result.txt')
+ test_jar_path = os.path.join(
+ constants.GetOutDirectory(
+ 'Release' if args.release else 'Debug'),
+ 'lib.java', 'findbugs_plugin_test.jar')
- if not options.only_analyze:
- options.only_analyze = 'org.chromium.tools.findbugs.plugin.*'
+ findbugs_command, findbugs_warnings = findbugs.Run(
+ None, 'org.chromium.tools.findbugs.plugin.*', None, None, None,
+ [test_jar_path])
- # crbug.com/449101
- # Temporary workaround to have the Android Clang Builder (dbg) bot
- # pass the findbugs_tests step.
- if not options.exclude:
- options.exclude = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
- 'android', 'findbugs_filter',
- 'findbugs_exclude.xml')
+ missing_warnings = _EXPECTED_WARNINGS.difference(findbugs_warnings)
+ if missing_warnings:
+ print 'Missing warnings:'
+ for w in missing_warnings:
+ print '%s' % str(w)
- return findbugs.Run(options)
+ unexpected_warnings = findbugs_warnings.difference(_EXPECTED_WARNINGS)
+ if unexpected_warnings:
+ print 'Unexpected warnings:'
+ for w in unexpected_warnings:
+ print '%s' % str(w)
+
+ return len(unexpected_warnings) + len(missing_warnings)
if __name__ == '__main__':
sys.exit(main(sys.argv))
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h
index 7659968..2ea8e54 100644
--- a/tools/clang/blink_gc_plugin/Edge.h
+++ b/tools/clang/blink_gc_plugin/Edge.h
@@ -39,14 +39,14 @@
class RecursiveEdgeVisitor : public EdgeVisitor {
public:
// Overrides that recursively walk the edges and record the path.
- virtual void VisitValue(Value*) override;
- virtual void VisitRawPtr(RawPtr*) override;
- virtual void VisitRefPtr(RefPtr*) override;
- virtual void VisitOwnPtr(OwnPtr*) override;
- virtual void VisitMember(Member*) override;
- virtual void VisitWeakMember(WeakMember*) override;
- virtual void VisitPersistent(Persistent*) override;
- virtual void VisitCollection(Collection*) override;
+ void VisitValue(Value*) override;
+ void VisitRawPtr(RawPtr*) override;
+ void VisitRefPtr(RefPtr*) override;
+ void VisitOwnPtr(OwnPtr*) override;
+ void VisitMember(Member*) override;
+ void VisitWeakMember(WeakMember*) override;
+ void VisitPersistent(Persistent*) override;
+ void VisitCollection(Collection*) override;
protected:
typedef std::deque<Edge*> Context;
diff --git a/tools/clang/blink_gc_plugin/JsonWriter.h b/tools/clang/blink_gc_plugin/JsonWriter.h
index 54a87aa..09504b3 100644
--- a/tools/clang/blink_gc_plugin/JsonWriter.h
+++ b/tools/clang/blink_gc_plugin/JsonWriter.h
@@ -7,66 +7,75 @@
#include "llvm/Support/raw_ostream.h"
+// TODO(hans): Remove this #ifdef after Clang is rolled past r234897.
+#ifdef LLVM_FORCE_HEAD_REVISION
+#define JSON_WRITER_STREAM std::unique_ptr<llvm::raw_ostream>
+#else
+#define JSON_WRITER_STREAM llvm::raw_fd_ostream*
+#endif
+
// Helper to write information for the points-to graph.
class JsonWriter {
public:
- static JsonWriter* from(llvm::raw_fd_ostream* os) {
- return os ? new JsonWriter(os) : 0;
+ static JsonWriter* from(JSON_WRITER_STREAM os) {
+ return os ? new JsonWriter(std::move(os)) : 0;
}
+#ifndef LLVM_FORCE_HEAD_REVISION
~JsonWriter() {
- os_.close();
+ delete os_;
}
+#endif
void OpenList() {
Separator();
- os_ << "[";
+ *os_ << "[";
state_.push(false);
}
void OpenList(const std::string key) {
Write(key);
- os_ << ":";
+ *os_ << ":";
OpenList();
}
void CloseList() {
- os_ << "]";
+ *os_ << "]";
state_.pop();
}
void OpenObject() {
Separator();
- os_ << "{";
+ *os_ << "{";
state_.push(false);
}
void CloseObject() {
- os_ << "}\n";
+ *os_ << "}\n";
state_.pop();
}
void Write(const size_t val) {
Separator();
- os_ << val;
+ *os_ << val;
}
void Write(const std::string val) {
Separator();
- os_ << "\"" << val << "\"";
+ *os_ << "\"" << val << "\"";
}
void Write(const std::string key, const size_t val) {
Separator();
- os_ << "\"" << key << "\":" << val;
+ *os_ << "\"" << key << "\":" << val;
}
void Write(const std::string key, const std::string val) {
Separator();
- os_ << "\"" << key << "\":\"" << val << "\"";
+ *os_ << "\"" << key << "\":\"" << val << "\"";
}
private:
- JsonWriter(llvm::raw_fd_ostream* os) : os_(*os) {}
+ JsonWriter(JSON_WRITER_STREAM os) : os_(std::move(os)) {}
void Separator() {
if (state_.empty())
return;
if (state_.top()) {
- os_ << ",";
+ *os_ << ",";
return;
}
state_.top() = true;
}
- llvm::raw_fd_ostream& os_;
+ JSON_WRITER_STREAM os_;
std::stack<bool> state_;
};
diff --git a/tools/clang/plugins/CMakeLists.txt b/tools/clang/plugins/CMakeLists.txt
index d17de19..e4eea86 100644
--- a/tools/clang/plugins/CMakeLists.txt
+++ b/tools/clang/plugins/CMakeLists.txt
@@ -1,15 +1,33 @@
-add_llvm_loadable_module(libFindBadConstructs
- ChromeClassTester.cpp
- FindBadConstructsAction.cpp
- FindBadConstructsConsumer.cpp
- )
+set(plugin_sources
+ ChromeClassTester.cpp
+ FindBadConstructsAction.cpp
+ FindBadConstructsConsumer.cpp)
-add_dependencies(libFindBadConstructs clang)
+if(WIN32)
+ # Clang doesn't support loadable modules on Windows. Unfortunately, building
+ # the plugin as a static library and linking clang against it doesn't work.
+ # Since clang doesn't reference any symbols in our static library, the linker
+ # strips it out completely.
+ # Instead, we rely on the fact that the SOURCES property of a target is no
+ # read-only after CMake 3.1 and use it to compile the plugin directly into
+ # clang...
+ cmake_minimum_required(VERSION 3.1)
+ # Paths must be absolute, since we're modifying a target in another directory.
+ set(absolute_sources "")
+ foreach(source ${plugin_sources})
+ list(APPEND absolute_sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
+ endforeach()
+ set_property(TARGET clang APPEND PROPERTY SOURCES ${absolute_sources})
+else()
+ add_llvm_loadable_module(libFindBadConstructs ${plugin_sources})
+ add_dependencies(libFindBadConstructs clang)
-cr_install(TARGETS libFindBadConstructs LIBRARY DESTINATION lib)
+ cr_install(TARGETS libFindBadConstructs LIBRARY DESTINATION lib)
-cr_add_test(plugins_test
- ${CMAKE_CURRENT_SOURCE_DIR}/tests/test.sh
- ${CMAKE_BINARY_DIR}/bin/clang
- $<TARGET_FILE:libFindBadConstructs>
- )
+ # TODO(dcheng): Rewrite the test framework so it works on Windows too.
+ cr_add_test(plugins_test
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/test.sh
+ ${CMAKE_BINARY_DIR}/bin/clang
+ $<TARGET_FILE:libFindBadConstructs>
+ )
+endif()
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 48d6a73..931da02 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -7,26 +7,20 @@
#include "ChromeClassTester.h"
-#include <sys/param.h>
+#include <algorithm>
#include "clang/AST/AST.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#ifdef LLVM_ON_UNIX
+#include <sys/param.h>
+#endif
+
using namespace clang;
namespace {
-bool starts_with(const std::string& one, const std::string& two) {
- return one.compare(0, two.size(), two) == 0;
-}
-
-std::string lstrip(const std::string& one, const std::string& two) {
- if (starts_with(one, two))
- return one.substr(two.size());
- return one;
-}
-
bool ends_with(const std::string& one, const std::string& two) {
if (two.size() > one.size())
return false;
@@ -101,14 +95,67 @@
std::string err;
err = "[chromium-style] ";
err += raw_error;
+ // TODO(dcheng): Re-enable -Werror for these diagnostics on Windows once all
+ // the pre-existing warnings are cleaned up. https://crbug.com/467287
DiagnosticIDs::Level level =
+#if !defined(LLVM_ON_WIN32)
diagnostic().getWarningsAsErrors() ?
DiagnosticIDs::Error :
+#endif
DiagnosticIDs::Warning;
unsigned id = diagnostic().getDiagnosticIDs()->getCustomDiagID(level, err);
DiagnosticBuilder builder = diagnostic().Report(full, id);
}
+bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
+ if (instance().getSourceManager().isInSystemHeader(loc))
+ return true;
+
+ std::string filename;
+ if (!GetFilename(loc, &filename)) {
+ // If the filename cannot be determined, simply treat this as a banned
+ // location, instead of going through the full lookup process.
+ return true;
+ }
+
+ // We need to special case scratch space; which is where clang does its
+ // macro expansion. We explicitly want to allow people to do otherwise bad
+ // things through macros that were defined due to third party libraries.
+ if (filename == "<scratch space>")
+ return true;
+
+ // Don't complain about autogenerated protobuf files.
+ if (ends_with(filename, ".pb.h")) {
+ return true;
+ }
+
+#if defined(LLVM_ON_UNIX)
+ // We need to munge the paths so that they are relative to the repository
+ // srcroot. We first resolve the symlinktastic relative path and then
+ // remove our known srcroot from it if needed.
+ char resolvedPath[MAXPATHLEN];
+ if (realpath(filename.c_str(), resolvedPath)) {
+ filename = resolvedPath;
+ }
+#endif
+
+#if defined(LLVM_ON_WIN32)
+ std::replace(filename.begin(), filename.end(), '\\', '/');
+#endif
+
+ for (const std::string& banned_dir : banned_directories_) {
+ // If any of the banned directories occur as a component in filename,
+ // this file is rejected.
+ assert(banned_dir.front() == '/' && "Banned dir must start with '/'");
+ assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
+
+ if (filename.find(banned_dir) != std::string::npos)
+ return true;
+ }
+
+ return false;
+}
+
bool ChromeClassTester::InBannedNamespace(const Decl* record) {
std::string n = GetNamespace(record);
if (!n.empty()) {
@@ -239,47 +286,6 @@
}
}
-bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
- std::string filename;
- if (!GetFilename(loc, &filename)) {
- // If the filename cannot be determined, simply treat this as a banned
- // location, instead of going through the full lookup process.
- return true;
- }
-
- // We need to special case scratch space; which is where clang does its
- // macro expansion. We explicitly want to allow people to do otherwise bad
- // things through macros that were defined due to third party libraries.
- if (filename == "<scratch space>")
- return true;
-
- // Don't complain about autogenerated protobuf files.
- if (ends_with(filename, ".pb.h")) {
- return true;
- }
-
- // We need to munge the paths so that they are relative to the repository
- // srcroot. We first resolve the symlinktastic relative path and then
- // remove our known srcroot from it if needed.
- char resolvedPath[MAXPATHLEN];
- if (realpath(filename.c_str(), resolvedPath)) {
- filename = resolvedPath;
- }
-
- for (size_t i = 0; i < banned_directories_.size(); ++i) {
- // If any of the banned directories occur as a component in filename,
- // this file is rejected.
- const std::string& banned_dir = banned_directories_[i];
- assert(banned_dir.front() == '/' && "Banned dir must start with '/'");
- assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
-
- if (filename.find(banned_dir) != std::string::npos)
- return true;
- }
-
- return false;
-}
-
bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
return ignored_record_names_.find(base_name) != ignored_record_names_.end();
}
diff --git a/tools/clang/plugins/ChromeClassTester.h b/tools/clang/plugins/ChromeClassTester.h
index 963b90f..ed65050 100644
--- a/tools/clang/plugins/ChromeClassTester.h
+++ b/tools/clang/plugins/ChromeClassTester.h
@@ -37,6 +37,10 @@
// namespace.
bool InBannedNamespace(const clang::Decl* record);
+ // Utility method for subclasses to check if the source location is in a
+ // directory the plugin should ignore.
+ bool InBannedDirectory(clang::SourceLocation loc);
+
// Utility method for subclasses to determine the namespace of the
// specified record, if any. Unnamed namespaces will be identified as
// "<anonymous namespace>".
@@ -64,7 +68,6 @@
// deliberately ignore) in HandleTagDeclDefinition().
std::string GetNamespaceImpl(const clang::DeclContext* context,
const std::string& candidate);
- bool InBannedDirectory(clang::SourceLocation loc);
bool IsIgnoredType(const std::string& base_name);
// Attempts to determine the filename for the given SourceLocation.
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index 770e255..20919a4 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -70,14 +70,15 @@
return decl->getQualifiedNameAsString() == "testing::Test";
}
+// Generates a fixit hint to remove the 'virtual' keyword.
+// Unfortunately, there doesn't seem to be a good way to determine the source
+// location of the 'virtual' keyword. It's available in Declarator, but that
+// isn't accessible from the AST. So instead, make an educated guess that the
+// first token is probably the virtual keyword. Strictly speaking, this doesn't
+// have to be true, but it probably will be.
+// TODO(dcheng): Add a warning to force virtual to always appear first ;-)
FixItHint FixItRemovalForVirtual(const SourceManager& manager,
const CXXMethodDecl* method) {
- // Unfortunately, there doesn't seem to be a good way to determine the
- // location of the 'virtual' keyword. It's available in Declarator, but that
- // isn't accessible from the AST. So instead, make an educated guess that the
- // first token is probably the virtual keyword. Strictly speaking, this
- // doesn't have to be true, but it probably will be.
- // TODO(dcheng): Add a warning to force virtual to always appear first ;-)
SourceRange range(method->getLocStart());
// Get the spelling loc just in case it was expanded from a macro.
SourceRange spelling_range(manager.getSpellingLoc(range.getBegin()));
@@ -413,32 +414,68 @@
// Complain if a method is annotated virtual && (override || final).
if (has_virtual && (override_attr || final_attr)) {
- diagnostic().Report(method->getLocStart(),
- diag_redundant_virtual_specifier_)
- << "'virtual'"
- << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
- << FixItRemovalForVirtual(manager, method);
+ // ... but only if virtual does not originate in a macro from a banned file.
+ // Note this is just an educated guess: the assumption here is that any
+ // macro for declaring methods will probably be at the start of the method's
+ // source range.
+ if (!InBannedDirectory(manager.getSpellingLoc(method->getLocStart()))) {
+ diagnostic().Report(method->getLocStart(),
+ diag_redundant_virtual_specifier_)
+ << "'virtual'"
+ << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
+ << FixItRemovalForVirtual(manager, method);
+ }
}
// Complain if a method is an override and is not annotated with override or
// final.
if (is_override && !override_attr && !final_attr) {
- SourceRange type_info_range =
- method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
- FullSourceLoc loc(type_info_range.getBegin(), manager);
-
- // Build the FixIt insertion point after the end of the method definition,
- // including any const-qualifiers and attributes, and before the opening
- // of the l-curly-brace (if inline) or the semi-color (if a declaration).
- SourceLocation spelling_end =
- manager.getSpellingLoc(type_info_range.getEnd());
- if (spelling_end.isValid()) {
- SourceLocation token_end =
- Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
- diagnostic().Report(token_end, diag_method_requires_override_)
- << FixItHint::CreateInsertion(token_end, " override");
+ SourceRange range = method->getSourceRange();
+ SourceLocation loc;
+ if (method->hasInlineBody()) {
+ loc = method->getBody()->getSourceRange().getBegin();
} else {
- diagnostic().Report(loc, diag_method_requires_override_);
+ // TODO(dcheng): We should probably use ASTContext's LangOptions here.
+ LangOptions lang_options;
+ loc = Lexer::getLocForEndOfToken(
+ manager.getSpellingLoc(range.getEnd()), 0,
+ manager, lang_options);
+ // The original code used the ending source loc of TypeSourceInfo's
+ // TypeLoc. Unfortunately, this breaks down in the presence of attributes.
+ // Attributes often appear at the end of a TypeLoc, e.g.
+ // virtual ULONG __stdcall AddRef()
+ // has a TypeSourceInfo that looks something like:
+ // ULONG AddRef() __attribute(stdcall)
+ // so a fix-it insertion would be generated to insert 'override' after
+ // __stdcall in the code as written.
+ // While using the spelling loc of the CXXMethodDecl fixes attribute
+ // handling, it breaks handling of "= 0" and similar constructs.. To work
+ // around this, scan backwards in the source text for a '=' or ')' token
+ // and adjust the location as needed...
+ for (SourceLocation l = loc.getLocWithOffset(-1);
+ l != manager.getLocForStartOfFile(manager.getFileID(loc));
+ l = l.getLocWithOffset(-1)) {
+ l = Lexer::GetBeginningOfToken(l, manager, lang_options);
+ Token token;
+ // getRawToken() returns *true* on failure. In that case, just give up
+ // and don't bother generating a possibly incorrect fix-it.
+ if (Lexer::getRawToken(l, token, manager, lang_options, true)) {
+ loc = SourceLocation();
+ break;
+ }
+ if (token.is(tok::r_paren)) {
+ break;
+ } else if (token.is(tok::equal)) {
+ loc = l;
+ break;
+ }
+ }
+ }
+ if (loc.isValid()) {
+ diagnostic().Report(loc, diag_method_requires_override_)
+ << FixItHint::CreateInsertion(loc, " override");
+ } else {
+ diagnostic().Report(range.getBegin(), diag_method_requires_override_);
}
}
@@ -559,8 +596,14 @@
// Adds either a warning or error, based on the current handling of
// -Werror.
DiagnosticsEngine::Level FindBadConstructsConsumer::getErrorLevel() {
+#if defined(LLVM_ON_WIN32)
+ // TODO(dcheng): Re-enable -Werror for these diagnostics on Windows once all
+ // the pre-existing warnings are cleaned up. https://crbug.com/467287
+ return DiagnosticsEngine::Warning;
+#else
return diagnostic().getWarningsAsErrors() ? DiagnosticsEngine::Error
: DiagnosticsEngine::Warning;
+#endif
}
// Returns true if |base| specifies one of the Chromium reference counted
diff --git a/tools/clang/plugins/tests/overridden_methods.txt b/tools/clang/plugins/tests/overridden_methods.txt
index 69ff2b1..bc2d1ac 100644
--- a/tools/clang/plugins/tests/overridden_methods.txt
+++ b/tools/clang/plugins/tests/overridden_methods.txt
@@ -1,82 +1,82 @@
In file included from overridden_methods.cpp:5:
-./overridden_methods.h:25:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:25:29: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethod() = 0;
- ^
- override
-./overridden_methods.h:46:26: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+./overridden_methods.h:46:27: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual ~DerivedClass() {}
- ^
- override
+ ^
+ override
./overridden_methods.h:48:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethod();
^
override
-./overridden_methods.h:52:34: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:52:35: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeInlineMethod() {}
- ^
- override
-./overridden_methods.h:56:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+./overridden_methods.h:56:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeConstMethod() const {}
- ^
- override
-./overridden_methods.h:58:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+./overridden_methods.h:58:54: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithExceptionSpec() throw() {}
- ^
- override
-./overridden_methods.h:61:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+./overridden_methods.h:61:68: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeConstMethodWithExceptionSpec() const throw(int) {}
- ^
- override
-./overridden_methods.h:63:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+./overridden_methods.h:63:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeNonPureBaseMethod() {}
- ^
- override
+ ^
+ override
./overridden_methods.h:65:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithComment(); // This is a comment.
^
override
-./overridden_methods.h:67:46: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:67:47: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithCommentAndBody() {} // This is a comment.
- ^
- override
-overridden_methods.cpp:15:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:15:29: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethod() = 0;
- ^
- override
-overridden_methods.cpp:22:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:22:41: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual ~ImplementationDerivedClass() {}
- ^
- override
+ ^
+ override
overridden_methods.cpp:24:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethod();
^
override
-overridden_methods.cpp:28:34: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+overridden_methods.cpp:28:35: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeInlineMethod() {}
- ^
- override
-overridden_methods.cpp:32:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:32:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeConstMethod() const {}
- ^
- override
-overridden_methods.cpp:34:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:34:54: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithExceptionSpec() throw() {}
- ^
- override
-overridden_methods.cpp:37:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:37:68: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeConstMethodWithExceptionSpec() const throw(int) {}
- ^
- override
-overridden_methods.cpp:39:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+overridden_methods.cpp:39:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeNonPureBaseMethod() {}
- ^
- override
+ ^
+ override
overridden_methods.cpp:41:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithComment(); // This is a comment.
^
override
-overridden_methods.cpp:43:46: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+overridden_methods.cpp:43:47: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void SomeMethodWithCommentAndBody() {} // This is a comment.
- ^
- override
+ ^
+ override
20 warnings generated.
diff --git a/tools/clang/plugins/tests/system/windows.h b/tools/clang/plugins/tests/system/windows.h
new file mode 100644
index 0000000..f93d5e2
--- /dev/null
+++ b/tools/clang/plugins/tests/system/windows.h
@@ -0,0 +1,10 @@
+// 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 TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
+#define TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
+
+#define STDMETHOD(x) virtual void x
+
+#endif // TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
diff --git a/tools/clang/plugins/tests/test.sh b/tools/clang/plugins/tests/test.sh
index ea21054..cf26252 100755
--- a/tools/clang/plugins/tests/test.sh
+++ b/tools/clang/plugins/tests/test.sh
@@ -12,6 +12,8 @@
failed_any_test=
+THIS_DIR="$(dirname "${0}")"
+
# Prints usage information.
usage() {
echo "Usage: $(basename "${0}")" \
@@ -38,6 +40,7 @@
local output="$("${CLANG_PATH}" -fsyntax-only -Wno-c++11-extensions \
-Wno-inconsistent-missing-override \
+ -isystem ${THIS_DIR}/system \
-Xclang -load -Xclang "${PLUGIN_PATH}" \
-Xclang -add-plugin -Xclang find-bad-constructs ${flags} ${1} 2>&1)"
local diffout="$(echo "${output}" | diff - "${2}")"
@@ -81,7 +84,7 @@
# The golden files assume that the cwd is this directory. To make the script
# work no matter what the cwd is, explicitly cd to there.
- cd "$(dirname "${0}")"
+ cd "${THIS_DIR}"
fi
for input in *.cpp; do
diff --git a/tools/clang/plugins/tests/virtual_specifiers.cpp b/tools/clang/plugins/tests/virtual_specifiers.cpp
index 28321e8..2103248 100644
--- a/tools/clang/plugins/tests/virtual_specifiers.cpp
+++ b/tools/clang/plugins/tests/virtual_specifiers.cpp
@@ -5,6 +5,8 @@
// Tests for chromium style checks for virtual/override/final specifiers on
// virtual methods.
+#include <windows.h>
+
// Purposely use macros to test that the FixIt hints don't try to remove the
// macro body.
#define OVERRIDE override
@@ -79,7 +81,13 @@
virtual void F() override = 0;
};
-// Finally, some simple sanity tests that overrides in the testing namespace
+// Test that the redundant virtual warning is suppressed when the virtual
+// keyword comes from a macro in a system header.
+class COMIsAwesome : public Base {
+ STDMETHOD(F)() override = 0;
+};
+
+// Some tests that overrides in the testing namespace
// don't trigger warnings, except for testing::Test.
namespace testing {
diff --git a/tools/clang/plugins/tests/virtual_specifiers.txt b/tools/clang/plugins/tests/virtual_specifiers.txt
index a51236c..135ebdd 100644
--- a/tools/clang/plugins/tests/virtual_specifiers.txt
+++ b/tools/clang/plugins/tests/virtual_specifiers.txt
@@ -1,69 +1,69 @@
-virtual_specifiers.cpp:36:21: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:38:22: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
~MissingOverride() {}
- ^
- override
-virtual_specifiers.cpp:37:11: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+virtual_specifiers.cpp:39:12: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
void F() {}
- ^
- override
-virtual_specifiers.cpp:43:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+ ^
+ override
+virtual_specifiers.cpp:45:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual ~VirtualAndOverride() OVERRIDE {}
^~~~~~~~
-virtual_specifiers.cpp:44:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:46:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual void F() OVERRIDE {}
^~~~~~~~
-virtual_specifiers.cpp:49:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
+virtual_specifiers.cpp:51:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
virtual ~VirtualAndFinal() FINAL {}
^~~~~~~~
-virtual_specifiers.cpp:50:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
+virtual_specifiers.cpp:52:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
virtual void F() FINAL {}
^~~~~~~~
-virtual_specifiers.cpp:55:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:57:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual ~VirtualAndOverrideFinal() OVERRIDE FINAL {}
^~~~~~~~
-virtual_specifiers.cpp:55:38: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:57:38: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
virtual ~VirtualAndOverrideFinal() OVERRIDE FINAL {}
^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
#define OVERRIDE override
^
-virtual_specifiers.cpp:56:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:58:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual void F() OVERRIDE FINAL {}
^~~~~~~~
-virtual_specifiers.cpp:56:20: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:58:20: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
virtual void F() OVERRIDE FINAL {}
^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
#define OVERRIDE override
^
-virtual_specifiers.cpp:61:23: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:63:23: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
~OverrideAndFinal() OVERRIDE FINAL {}
^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
#define OVERRIDE override
^
-virtual_specifiers.cpp:62:12: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:64:12: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
void F() OVERRIDE FINAL {}
^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
#define OVERRIDE override
^
-virtual_specifiers.cpp:67:19: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:69:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual void F() = 0;
- ^
- override
-virtual_specifiers.cpp:71:11: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+ ^
+ override
+virtual_specifiers.cpp:73:12: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
void F() = 0;
- ^
- override
-virtual_specifiers.cpp:79:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+ ^
+ override
+virtual_specifiers.cpp:81:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual void F() override = 0;
^~~~~~~~
-virtual_specifiers.cpp:102:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:110:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
virtual ~MyTest();
^
override
-virtual_specifiers.cpp:103:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:111:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
virtual void SetUp() override;
^~~~~~~~
17 warnings generated.
diff --git a/tools/clang/scripts/blink_gc_plugin_flags.sh b/tools/clang/scripts/blink_gc_plugin_flags.sh
index 38ea72d..96dcade 100755
--- a/tools/clang/scripts/blink_gc_plugin_flags.sh
+++ b/tools/clang/scripts/blink_gc_plugin_flags.sh
@@ -25,8 +25,10 @@
FLAGS="$FLAGS $PREFIX warn-raw-ptr"
elif [[ "$arg" = "warn-unneeded-finalizer=1" ]]; then
FLAGS="$FLAGS $PREFIX warn-unneeded-finalizer"
+ elif [[ "$arg" = custom_clang_lib_path=* ]]; then
+ CLANG_LIB_PATH="$(cd "${arg#*=}" && echo $PWD)"
fi
done
-echo -Xclang -load -Xclang $CLANG_LIB_PATH/libBlinkGCPlugin.$LIBSUFFIX \
+echo -Xclang -load -Xclang \"$CLANG_LIB_PATH/libBlinkGCPlugin.$LIBSUFFIX\" \
-Xclang -add-plugin -Xclang blink-gc-plugin $FLAGS
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 7c4a214..30d9ce9 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -6,6 +6,7 @@
"""Windows can't run .sh files, so this is a Python implementation of
update.sh. This script should replace update.sh on all platforms eventually."""
+import argparse
import os
import re
import shutil
@@ -24,12 +25,13 @@
# in bringup. Use a pinned revision to make it slightly more stable.
if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and
not 'LLVM_FORCE_HEAD_REVISION' in os.environ):
- LLVM_WIN_REVISION = '232554'
+ LLVM_WIN_REVISION = '235793'
# Path constants. (All of these should be absolute paths.)
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
LLVM_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm')
+CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'chrometools')
LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
'Release+Asserts')
COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, '32bit-compiler-rt')
@@ -129,6 +131,32 @@
RunCommand(command)
+def DeleteChromeToolsShim():
+ shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True)
+
+
+def CreateChromeToolsShim():
+ """Hooks the Chrome tools into the LLVM build.
+
+ Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build
+ detects implicit tools in the tools subdirectory, so this helper install a
+ shim CMakeLists.txt that forwards to the real directory for the Chrome tools.
+
+ Note that the shim directory name intentionally has no - or _. The implicit
+ tool detection logic munges them in a weird way."""
+ assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
+ os.mkdir(CHROME_TOOLS_SHIM_DIR)
+ with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
+ f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
+ 'Do not edit.\n')
+ f.write('# Since tools/clang is located in another directory, use the \n')
+ f.write('# two arg version to specify where build artifacts go. CMake\n')
+ f.write('# disallows reuse of the same binary dir for multiple source\n')
+ f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
+ f.write('add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
+ '${CMAKE_CURRENT_BINARY_DIR}/a)\n')
+
+
def AddCMakeToPath():
"""Look for CMake and add it to PATH if it's not there already."""
try:
@@ -181,30 +209,38 @@
return ''
-def UpdateClang():
+def UpdateClang(args):
print 'Updating Clang to %s...' % (LLVM_WIN_REVISION)
if LLVM_WIN_REVISION != 'HEAD' and ReadStampFile() == LLVM_WIN_REVISION:
print 'Already up to date.'
return 0
AddCMakeToPath()
- ClobberChromiumBuildFiles()
+ if args.clobber:
+ ClobberChromiumBuildFiles()
# Reset the stamp file in case the build is unsuccessful.
WriteStampFile('')
+ DeleteChromeToolsShim();
Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR)
Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
+ CreateChromeToolsShim();
if not os.path.exists(LLVM_BUILD_DIR):
os.makedirs(LLVM_BUILD_DIR)
os.chdir(LLVM_BUILD_DIR)
+ cmake_args = ['-GNinja', '-DCMAKE_BUILD_TYPE=Release',
+ '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(),
+ '-DCHROMIUM_TOOLS_SRC=%s' % os.path.join(
+ CHROMIUM_DIR, 'tools', 'clang'),
+ '-DCHROMIUM_TOOLS=%s' % ';'.join(args.tools)]
+
RunCommand(GetVSVersion().SetupScript('x64') +
- ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release',
- '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(), LLVM_DIR])
+ ['&&', 'cmake'] + cmake_args + [LLVM_DIR])
RunCommand(GetVSVersion().SetupScript('x64') + ['&&', 'ninja', 'all'])
# Do an x86 build of compiler-rt to get the 32-bit ASan run-time.
@@ -213,8 +249,7 @@
os.makedirs(COMPILER_RT_BUILD_DIR)
os.chdir(COMPILER_RT_BUILD_DIR)
RunCommand(GetVSVersion().SetupScript('x86') +
- ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release',
- '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR])
+ ['&&', 'cmake'] + cmake_args + [LLVM_DIR])
RunCommand(GetVSVersion().SetupScript('x86') + ['&&', 'ninja', 'compiler-rt'])
# TODO(hans): Make this (and the .gypi and .isolate files) version number
@@ -276,7 +311,13 @@
print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
return 0
- return UpdateClang()
+ parser = argparse.ArgumentParser(description='Build Clang.')
+ parser.add_argument('--no-clobber', dest='clobber', action='store_false')
+ parser.add_argument('--tools', nargs='*', default=['plugins'])
+ # For now, this flag is only used for the non-Windows flow, but argparser gets
+ # mad if it sees a flag it doesn't recognize.
+ parser.add_argument('--if-needed', action='store_true')
+ return UpdateClang(parser.parse_args())
if __name__ == '__main__':
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 10a4645..f0dbeb0 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -11,7 +11,7 @@
CLANG_REVISION=233105
# This is incremented when pushing a new build of Clang at the same revision.
-CLANG_SUB_REVISION=1
+CLANG_SUB_REVISION=2
PACKAGE_VERSION="${CLANG_REVISION}-${CLANG_SUB_REVISION}"
@@ -63,13 +63,6 @@
PACKAGE_VERSION="${CLANG_REVISION}-0"
fi
-# Use both the clang revision and the plugin revisions to test for updates.
-BLINKGCPLUGIN_REVISION=\
-$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
- | cut -d ' ' -f 2 | tr -cd '[0-9]')
-CLANG_AND_PLUGINS_REVISION="${CLANG_REVISION}-${BLINKGCPLUGIN_REVISION}"
-
-
OS="$(uname -s)"
# Parse command line options.
@@ -190,14 +183,13 @@
fi
fi
- if [[ "${OS}" == "Linux" ]]; then
- # TODO(hans): Might need to make this work on Mac eventually.
+ if [[ "${OS}" == "Linux" || "${OS}" == "Darwin" ]]; then
if [[ $(cmake --version | grep -Eo '[0-9.]+') < "3.0" ]]; then
# We need a newer CMake version.
if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/cmake310" ]]; then
echo "Downloading pre-built CMake 3.10..."
mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
- curl --fail -L "${CDS_URL}/tools/cmake310.tgz" | \
+ curl --fail -L "${CDS_URL}/tools/cmake310_${OS}.tgz" | \
tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
echo Done
fi
@@ -322,6 +314,7 @@
"${CLANG_DIR}/test/SemaCXX/typo-correction-delayed.cpp" \
"${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc" \
"${COMPILER_RT_DIR}/test/tsan/signal_segv_handler.cc" \
+ "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_coverage_libcdep.cc" \
; do
if [[ -e "${i}" ]]; then
rm -f "${i}" # For unversioned files.
@@ -404,6 +397,27 @@
patch -p0
popd
+ # Cherry-pick r234010 [sancov] Shrink pc array on Android back to 2**24."
+ pushd "${COMPILER_RT_DIR}"
+ cat << 'EOF' |
+diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+index 4b976fc..cfd9e7e 100644
+--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
++++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+@@ -109,7 +109,8 @@ class CoverageData {
+
+ // Maximal size pc array may ever grow.
+ // We MmapNoReserve this space to ensure that the array is contiguous.
+- static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
++ static const uptr kPcArrayMaxSize =
++ FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27);
+ // The amount file mapping for the pc array is grown by.
+ static const uptr kPcArrayMmapSize = 64 * 1024;
+
+EOF
+ patch -p1
+ popd
+
# This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
pushd "${LLVM_DIR}"
cat << 'EOF' |
@@ -551,6 +565,14 @@
BINUTILS_INCDIR="${ABS_BINUTILS_DIR}/Linux_x64/Release/include"
fi
+
+# If building at head, define a macro that plugins can use for #ifdefing
+# out code that builds at head, but not at CLANG_REVISION or vice versa.
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+ CFLAGS="${CFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+ CXXFLAGS="${CXXFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+fi
+
# Hook the Chromium tools into the LLVM build. Several Chromium tools have
# dependencies on LLVM/Clang libraries. The LLVM build detects implicit tools
# in the tools subdirectory, so install a shim CMakeLists.txt that forwards to
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index a64ae83..d56ba05 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -45,6 +45,9 @@
"content/app/resources/content_resources.grd": {
"structures": [4700],
},
+ "third_party/WebKit/public/blink_image_resources.grd": {
+ "structures": [4750],
+ },
"ui/resources/ui_resources.grd": {
"structures": [5500],
},
@@ -166,8 +169,11 @@
},
# iOS resources overlap with ash, chromeos and extensions_api, as these are
# not used on iOS.
+ "ios/chrome/app/strings/ios_strings_resources.grd": {
+ "messages": [26000],
+ },
"ios/chrome/app/theme/ios_theme_resources.grd": {
- "structures": [26000],
+ "structures": [27000],
},
"ash/ash_strings.grd": {
"messages": [26000],
@@ -237,10 +243,11 @@
"includes": [30250],
},
"components/resources/components_scaled_resources.grd": {
- "structures": [30350],
+ "structures": [30280],
},
"third_party/WebKit/public/blink_resources.grd": {
- "includes": [30500],
+ "includes": [30350],
+ "structures": [30650],
},
"chrome/browser/devtools/device/webrtc/resources.grd": {
"includes": [30800],
diff --git a/tools/valgrind/.gitignore b/tools/valgrind/.gitignore
new file mode 100644
index 0000000..a77c220
--- /dev/null
+++ b/tools/valgrind/.gitignore
@@ -0,0 +1,2 @@
+buildlogs.tmp
+waterfall.tmp
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 554beb3..e8074f3 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -568,7 +568,7 @@
# http://crbug.com/176908: Don't launch a browser when done.
"--no-show-results",
"--nocheck-sys-deps",
- "--additional-drt-flag=--no-sandbox"]
+ "--additional-driver-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 4e084a7..e54404b 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -478,10 +478,8 @@
name=http://crbug.com/371368
system call NtCreateNamedPipeFile
KERNELBASE.dll!CreateNamedPipeW
-ipc.dll!IPC::Channel::ChannelImpl::CreatePipe
-ipc.dll!IPC::Channel::ChannelImpl::ChannelImpl
-ipc.dll!IPC::Channel::Channel
-ipc.dll!IPC::ChannelProxy::Context::CreateChannel
+ipc.dll!IPC::ChannelWin::CreatePipe
+ipc.dll!IPC::ChannelWin::ChannelWin
HANDLE LEAK
name=http://crbug.com/371942
@@ -755,7 +753,24 @@
name=http://crbug.com/463261
...
blink_web.dll!blink::WebFrameWidgetImpl::selectionBounds
-content.dll!content::RenderWidget::GetSelectionBounds
+...
content.dll!content::RenderWidget::UpdateSelectionBounds
content.dll!content::RenderWidget::willBeginCompositorFrame
cc.dll!base::internal::InvokeHelper<>::MakeItSo
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/476586
+*!blink::WebFrameWidgetImpl::beginFrame
+*!content::RenderWidgetCompositor::BeginMainFrame
+*!cc::LayerTreeHost::BeginMainFrame
+*!cc::ThreadProxy::BeginMainFrame
+*!base::internal::InvokeHelper<>::MakeItSo
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/476586b
+*!blink::PageWidgetDelegate::animate
+*!blink::WebFrameWidgetImpl::beginFrame
+*!content::RenderWidgetCompositor::BeginMainFrame
+*!cc::LayerTreeHost::BeginMainFrame
+*!cc::ThreadProxy::BeginMainFrame
+*!base::internal::InvokeHelper<>::MakeItSo
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 81fcb31..b48c199 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1916,10 +1916,36 @@
*!encode_nonrd_sb_row
*!vp9_encode_tile
+UNADDRESSABLE ACCESS
+name=bug_470055
+blink_web.dll!blink::*::focused*Frame
+blink_web.dll!blink::WebFrameWidgetImpl::selectionBounds
+content.dll!content::RenderWidget::UpdateSelectionBounds
+content.dll!content::RenderWidget::willBeginCompositorFrame
+
UNINITIALIZED READ
-name=bug_468638
-*!egl::ConfigSorter::operator()
-*!std::_Insertion_sort1<>
-*!std::_Sort<>
-*!egl::ConfigSet::filter
-*!ConfigSetTest_*_BitSizes_Test::TestBody
+name=bug_470848
+blink_platform.dll!blink::Heap::RegionTree::lookup
+*!testing::internal::HandleExceptionsInMethodIfSupported<>
+
+HANDLE LEAK
+name=https://crbug.com/480741
+system call NtDuplicateObject
+KERNELBASE.dll!DuplicateHandle
+KERNEL32.dll!DuplicateHandle
+base.dll!base::SharedMemory::ShareToProcessCommon
+gl_wrapper.dll!gfx::GLImageSharedMemory::Initialize
+content.dll!content::GpuChannel::CreateImageForGpuMemoryBuffer
+content.dll!content::GpuCommandBufferStub::OnCreateImage
+
+HANDLE LEAK
+name=https://crbug.com/481305
+system call NtCreateSection
+KERNELBASE.dll!CreateFileMappingW
+base.dll!base::SharedMemory::Create
+base.dll!base::SharedMemory::CreateAnonymous
+content.dll!content::ChildThreadImpl::AllocateSharedMemory
+content.dll!content::RenderThreadImpl::HostAllocateSharedMemoryBuffer
+content.dll!content::RenderThreadImpl::AllocateSharedMemory
+...
+content.dll!content::WebGraphicsContext3DCommandBufferImpl::CreateContext
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
index cc442bc..ec243c5 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
@@ -36,3 +36,5 @@
# so we can avoid excluding this for light mode.
MessageLoopTestTypeUI.RecursiveDenial3
+# https://crbug.com/481231
+WinHeapDumpProviderTest.DumpInto
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
index 937bf28..ee2d424 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
@@ -18,3 +18,6 @@
MessageLoopTestTypeUI.RecursivePosts
MessageLoopTestTypeIO.RecursivePosts
MessageLoopTestTypeDefault.RecursivePosts
+
+# Check-fails on Valgrind/Mac, see https://crbug.com/481290
+MessagePumpLibeventTest.QuitWatcher
diff --git a/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt
new file mode 100644
index 0000000..c080b7a
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt
@@ -0,0 +1,3 @@
+# https://crbug.com/480650: fails
+HarfBuzzShaperTest.ResolveCandidateRunsLatin
+HarfBuzzShaperTest.ResolveCandidateRunsLeadingCommon
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index 371b4bf..6823027 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -30,3 +30,8 @@
# http://crbug.com/459000
ClipboardApiTest.HostedAppNoPermission
+# http://crbug.com/475172
+BasicExtensionSettingsWebUITest.testUninstall
+
+# https://crbug.com/480721
+OutOfProcessProxyResolverBrowserTest.Verify
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
index f5dcbb0..b5e2b57 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
@@ -137,6 +137,8 @@
Pe*
Plat*Bro*
Policy*H*
+# PopupBlockerBrowserTest.TapGestureWithCtrlKey
+Pop*
Port*
Prefe*
PrefsF*
@@ -177,7 +179,8 @@
SRC*.Fr*
SSL*ed
Sup*Mo*
-Str*
+# StartupBrowserCreatorTest.ProfilesLaunchedAfterCrash
+St*orTest.*
SyncF*
SyncInt*
Sys*Di*
diff --git a/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
index 5a76d89..7946e97 100644
--- a/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
@@ -10,6 +10,8 @@
# http://crbug.com/416643
LayerTreeHostCopyRequestTestMultipleRequests.GLRenderer_RunSingleThread
LayerTreeHostCopyRequestTestMultipleRequests.SoftwareRenderer_RunSingleThread
+LayerTreeHostTestReadyToDrawNonEmpty.*
+LayerTreeHostTestMaxTransferBufferUsageBytes.*
# http://crbug.com/430400
PixelResourceTest*
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index 2ec3183..55df649 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -28,6 +28,7 @@
# http://crbug.com/456131
BrowserSideNavigationBrowserTest.BrowserInitiatedNavigations
+BrowserSideNavigationBrowserTest.FailedNavigation
# http://crbug.com/464029
WebRtcBrowserTest.CallAndModifyStream
@@ -35,3 +36,6 @@
# http://crbug.com/464033
RenderFrameHostImplBrowserTest.IsFocused_AtLoad
RenderFrameHostImplBrowserTest.IsFocused_Widget
+
+# http://crbug.com/470507
+SRC_ClearKey/EncryptedMediaTest.Playback_VideoClearAudio_WebM/0
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
index 664400d..0e91022 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
@@ -16,6 +16,7 @@
Http/MediaTest.VideoTulipWebm/0
IndexedDBBrowserTest.DeleteCompactsBackingStore
MSE_ClearKey/EncryptedMediaTest.FrameSizeChangeVideo/0
+MSE_ClearKey/EncryptedMediaTest.Playback_VideoAudio_WebM/0
OutOfProcessPPAPITest.MediaStreamAudioTrack
OutOfProcessPPAPITest.NetworkProxy
OutOfProcessPPAPITest.VideoDecoder
@@ -51,3 +52,6 @@
WebRtcBrowserTest.CanSetupVideoCallWith4To3AspectRatio
WebRtcBrowserTest.NegotiateOfferWithBLine
WebRtcBrowserTest.CanMakeAudioCallAndThenRenegotiateToVideo
+
+# https://crbug.com/480750
+MSE_ClearKey/EncryptedMediaTest.Playback_AudioClearVideo_WebM/0
diff --git a/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt
new file mode 100644
index 0000000..d73c572
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/470517
+VideoRendererImplTest.Underflow
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
index d804f42..6e8f352 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
@@ -82,3 +82,6 @@
# http://crbug.com/467004
SigninErrorNotifierTest.NoErrorAuthStatusProviders
+
+# http://crbug.com/473689
+ManagePasswordsBubbleModelTest.CloseWithoutLogging
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
index fa0595b..bae79ce 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
@@ -13,3 +13,9 @@
# Test fail: crbug.com/314216
ExtensionIconManagerTest.LoadComponentExtensionResource
+
+# Test fail: crbug.com/473689
+ManagePasswordsBubbleModelTest.CloseWithoutLogging
+
+# Test fail: crbug.com/476731
+PluginInfoMessageFilterTest.FindEnabledPlugin
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 4374a72..56948ef 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -2961,9 +2961,8 @@
fun:_Znw*
fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b
- fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC1ERKN4base7WeakPtrIS0_EE
- fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE
- fun:_ZN8chromeos24HostResolverImplChromeOSC1E13*
+ fun:_ZN3net16HostResolverImpl16LoopbackProbeJob*
+ fun:_ZN3net16HostResolverImplC*
}
{
bug_387993
@@ -3012,7 +3011,7 @@
bug_388668
Memcheck:Leak
fun:_Znw*
- fun:_ZN20data_reduction_proxy69DataReductionProxyUsageStatsTest_isDataReductionProxyUnreachable_Test8TestBodyEv
+ fun:_ZN20data_reduction_proxy69DataReductionProxyBypassStatsTest_isDataReductionProxyUnreachable_Test8TestBodyEv
}
{
bug_392912
@@ -3025,18 +3024,6 @@
fun:_ZN14SkBitmapDevice8drawPathERK6SkDrawRK6SkPathRK7SkPaintPK8SkMatrixb
}
{
- bug_392936
- Memcheck:Leak
- fun:_Znw*
- fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
- fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b
- fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC2ERKN4base7WeakPtrIS0_EE
- fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE
- fun:_ZN8chromeos24HostResolverImplChromeOSC1E13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerERKN3net12HostResolver7OptionsEPNS7_6NetLogE
- fun:_ZN8chromeos24HostResolverImplChromeOS25CreateHostResolverForTestE13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerE
- fun:_ZN28HostResolverImplChromeOSTest22InitializeHostResolverEv
-}
-{
bug_394558
Memcheck:Leak
fun:_Znw*
@@ -3629,9 +3616,6 @@
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
@@ -3656,4 +3640,15 @@
fun:_ZN4base12_GLOBAL__N_112WorkerThread10ThreadMainEv
fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
}
-
+{
+ bug_476940
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF9BitVector13OutOfLineBits6createEm
+ fun:_ZN3WTF9BitVector15resizeOutOfLineEm
+ fun:_ZN3WTF9BitVector10ensureSizeEm
+ fun:_ZN3WTF9BitVectorC2Em
+ fun:_ZN5blink10UseCounter9CountBitsC2Ev
+ fun:_ZN5blink10UseCounterC1Ev
+ fun:_ZN5blink4PageC1ERNS0_11PageClientsE
+}
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt
index c9ed9bf..ac9c687 100644
--- a/tools/valgrind/memcheck/suppressions_mac.txt
+++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -94,6 +94,14 @@
fun:__CFRunLoopRun
...
}
+{
+ # See also http://openradar.appspot.com/20698633
+ bug_481286
+ Memcheck:Leak
+ ...
+ fun:_ZN8Security13PluginSession6mallocEm
+ fun:_Z20CL_extractCSSMKeyNSSRK33cssm_x509_subject_public_key_infoRN8Security9AllocatorEPK11DecodedCert
+}
# Intentional leaks in AppKit, for an OS-level cache. Only appear on the first
# run of each reboot. See also issues 105525, 257276, 340847.
{
diff --git a/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java b/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
index c868f32..c40b0a9 100644
--- a/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
+++ b/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
@@ -13,8 +13,6 @@
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
-import org.chromium.base.ApiCompatibilityUtils;
-
/**
* Encapsulates a single gradient view of the HSV color display, including its label, gradient
* view and seek bar.
@@ -90,6 +88,6 @@
} else {
mGradientDrawable.setColors(mGradientColors);
}
- ApiCompatibilityUtils.setBackgroundForView(mGradientView, mGradientDrawable);
+ mGradientView.setBackground(mGradientDrawable);
}
}
diff --git a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
index 2b561d1..51bb6b6 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
@@ -15,8 +15,6 @@
import android.widget.ArrayAdapter;
import android.widget.TextView;
-import org.chromium.base.ApiCompatibilityUtils;
-
import java.util.List;
import java.util.Set;
@@ -59,7 +57,7 @@
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = inflater.inflate(R.layout.dropdown_item, null);
- ApiCompatibilityUtils.setBackgroundForView(layout, new DropdownDividerDrawable());
+ layout.setBackground(new DropdownDividerDrawable());
}
DropdownItem item = getItem(position);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 33886ee..536a63c 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -63,13 +63,6 @@
libs += [ "jnigraphics" ]
}
-
- if (is_android && is_android_webview_build) {
- deps += [
- #TODO(GYP): port this component to GN.
- #"//ui/android:ui_java",
- ]
- }
}
if (is_android) {
diff --git a/ui/events/gesture_detection/scale_gesture_detector.cc b/ui/events/gesture_detection/scale_gesture_detector.cc
index 7afe91f..a8316c7 100644
--- a/ui/events/gesture_detection/scale_gesture_detector.cc
+++ b/ui/events/gesture_detection/scale_gesture_detector.cc
@@ -7,7 +7,6 @@
#include <limits.h>
#include <cmath>
-#include "base/float_util.h"
#include "base/logging.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/gesture_detection/scale_gesture_listeners.h"
@@ -285,7 +284,7 @@
float total = 0;
int sample_count = 0;
for (int i = 0; i < count; i++) {
- const bool has_last_accepted = !base::IsNaN(touch_history_last_accepted_);
+ const bool has_last_accepted = !std::isnan(touch_history_last_accepted_);
const int history_size = static_cast<int>(ev.GetHistorySize());
const int pointersample_count = history_size + 1;
for (int h = 0; h < pointersample_count; h++) {
@@ -301,10 +300,10 @@
major = touch_max_major_;
total += major;
- if (base::IsNaN(touch_upper_) || major > touch_upper_) {
+ if (std::isnan(touch_upper_) || major > touch_upper_) {
touch_upper_ = major;
}
- if (base::IsNaN(touch_lower_) || major < touch_lower_) {
+ if (std::isnan(touch_lower_) || major < touch_lower_) {
touch_lower_ = major;
}
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 9e66cc2..3ca2c09 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -111,11 +111,6 @@
"display_observer.cc",
]
- # TODO(GYP) re-enable when base_java exists.
- #if (!is_android_webview_build) {
- # deps += [ "//base:base_java" ]
- #}
-
# TODO(jdduke): Revisit optimization after gauging benefit, crbug/419051.
if (!is_debug) {
configs -= [ "//build/config/compiler:optimize" ]
diff --git a/ui/gfx/display_change_notifier_unittest.cc b/ui/gfx/display_change_notifier_unittest.cc
index 47b5bd0..9c1dda2 100644
--- a/ui/gfx/display_change_notifier_unittest.cc
+++ b/ui/gfx/display_change_notifier_unittest.cc
@@ -70,13 +70,6 @@
EXPECT_EQ(1, observer.display_added());
}
-TEST(DisplayChangeNotifierTest, AddObserver_Null) {
- DisplayChangeNotifier change_notifier;
-
- change_notifier.AddObserver(NULL);
- // Should not crash.
-}
-
TEST(DisplayChangeNotifier, RemoveObserver_Smoke) {
DisplayChangeNotifier change_notifier;
MockDisplayObserver observer;
@@ -93,13 +86,6 @@
EXPECT_EQ(0, observer.display_added());
}
-TEST(DisplayChangeNotifierTest, RemoveObserver_Null) {
- DisplayChangeNotifier change_notifier;
-
- change_notifier.RemoveObserver(NULL);
- // Should not crash.
-}
-
TEST(DisplayChangeNotifierTest, RemoveObserver_Unknown) {
DisplayChangeNotifier change_notifier;
MockDisplayObserver observer;
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 29bed31..04dea9c 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -208,7 +208,7 @@
]
}
- if (is_android && !is_android_webview_build) {
+ if (is_android) {
deps += [ "//ui/android:ui_java" ]
}
}