Update from https://crrev.com/303153
This updates from chromium https://crrev.com/303153 aka
f9567f85788355bf3da8df030cbc232421d00b7d with the following additional
changes:
Update skia_build.patch and cc_strip_video.patch with trivial changes.
Update gpu::CommandBuffer state serialization for upstream changes.
Update ui/compositor/layer for upstream cc::SurfaceLayer changes.
TBR=jam@chromium.org
Review URL: https://codereview.chromium.org/706203003
diff --git a/base/BUILD.gn b/base/BUILD.gn
index fdd4572..84beb15 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -858,7 +858,7 @@
]
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- cflags = [ "/wd4267" ]
+ #cflags = [ "/wd4267" ]
libs = [
"cfgmgr32.lib",
diff --git a/base/PRESUBMIT.py b/base/PRESUBMIT.py
index 4b366d9..46ab02e 100644
--- a/base/PRESUBMIT.py
+++ b/base/PRESUBMIT.py
@@ -14,6 +14,7 @@
files = []
for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
if (f.LocalPath().startswith('base/') and
+ not "/ios/" in f.LocalPath() and
not "/test/" in f.LocalPath() and
not f.LocalPath().endswith('_unittest.mm') and
not f.LocalPath().endswith('mac/sdk_forward_declarations.h')):
diff --git a/base/android/field_trial_list.cc b/base/android/field_trial_list.cc
index 13f3cc5..9cb38d2 100644
--- a/base/android/field_trial_list.cc
+++ b/base/android/field_trial_list.cc
@@ -22,6 +22,11 @@
base::FieldTrialList::FindFullName(trial_name)).Release();
}
+static jboolean TrialExists(JNIEnv* env, jclass clazz, jstring jtrial_name) {
+ std::string trial_name(ConvertJavaStringToUTF8(env, jtrial_name));
+ return base::FieldTrialList::TrialExists(trial_name);
+}
+
namespace base {
namespace android {
diff --git a/base/android/java/src/org/chromium/base/FieldTrialList.java b/base/android/java/src/org/chromium/base/FieldTrialList.java
index 6c1f31c..5fc9a1f 100644
--- a/base/android/java/src/org/chromium/base/FieldTrialList.java
+++ b/base/android/java/src/org/chromium/base/FieldTrialList.java
@@ -20,5 +20,14 @@
return nativeFindFullName(trialName);
}
+ /**
+ * @param trialName The name of the trial to get the group for.
+ * @return Whether the trial exists or not.
+ */
+ public static boolean trialExists(String trialName) {
+ return nativeTrialExists(trialName);
+ }
+
private static native String nativeFindFullName(String trialName);
+ private static native boolean nativeTrialExists(String trialName);
}
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 97afbea..28c688d 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
@@ -55,17 +55,17 @@
private static boolean sIsUsingBrowserSharedRelros = false;
private static boolean sLoadAtFixedAddressFailed = false;
- // One-way switch becomes true if the device supports loading the Chromium
- // library directly from the APK.
- private static boolean sLibraryLoadFromApkSupported = false;
+ // One-way switch becomes true if the device supports memory mapping the
+ // APK file with executable permissions.
+ private static boolean sMapApkWithExecPermission = false;
// One-way switch becomes true if the Chromium library was loaded from the
// APK file directly.
private static boolean sLibraryWasLoadedFromApk = false;
// One-way switch becomes false if the Chromium library should be loaded
- // directly from the APK file but it was not aligned.
- private static boolean sLibraryWasAlignedInApk = true;
+ // directly from the APK file but it was compressed or not aligned.
+ private static boolean sLibraryIsMappableInApk = true;
// One-way switch becomes true if the system library loading failed,
// and the right native library was found and loaded by the hack.
@@ -176,12 +176,20 @@
if (useChromiumLinker) {
String apkFilePath = null;
+ boolean useMapExecSupportFallback = false;
- // Check if the device supports loading a library directly from the APK file.
+ // Check if the device supports memory mapping the APK file
+ // with executable permissions.
if (context != null) {
apkFilePath = context.getApplicationInfo().sourceDir;
- sLibraryLoadFromApkSupported = Linker.checkLibraryLoadFromApkSupport(
- apkFilePath);
+ sMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
+ if (!sMapApkWithExecPermission && Linker.isInZipFile()) {
+ Log.w(TAG, "the no map executable support fallback will be used because"
+ + " memory mapping the APK file with executable permissions is"
+ + " not supported");
+ Linker.enableNoMapExecSupportFallback();
+ useMapExecSupportFallback = true;
+ }
} else {
Log.w(TAG, "could not check load from APK support due to null context");
}
@@ -203,18 +211,22 @@
String libFilePath = System.mapLibraryName(library);
if (apkFilePath != null && Linker.isInZipFile()) {
// The library is in the APK file.
- if (!Linker.checkLibraryAlignedInApk(apkFilePath, libFilePath)) {
- sLibraryWasAlignedInApk = false;
+ if (!Linker.checkLibraryIsMappableInApk(apkFilePath, libFilePath)) {
+ sLibraryIsMappableInApk = false;
}
- if (!sLibraryLoadFromApkSupported || sLibraryWasAlignedInApk) {
- // Load directly from the APK (or use memory fallback, see
- // crazy_linker_elf_loader.cpp).
- Log.i(TAG, "Loading " + library + " directly from within "
- + apkFilePath);
+ if (sLibraryIsMappableInApk || useMapExecSupportFallback) {
+ // Load directly from the APK (or use the no map executable
+ // support fallback, see crazy_linker_elf_loader.cpp).
zipFilePath = apkFilePath;
+ Log.i(TAG, "Loading " + library + " "
+ + (useMapExecSupportFallback
+ ? "using no map executable support fallback"
+ : "directly")
+ + " from within " + apkFilePath);
} else {
- // Fallback.
- Log.i(TAG, "Loading " + library + " using fallback from within "
+ // Unpack library fallback.
+ Log.i(TAG, "Loading " + library
+ + " using unpack library fallback from within "
+ apkFilePath);
libFilePath = LibraryLoaderHelper.buildFallbackLibrary(
context, library);
@@ -299,10 +311,10 @@
// Load a native shared library with the Chromium linker. If the zip file
// path is not null, the library is loaded directly from the zip file.
private static void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
+ Linker.loadLibrary(zipFilePath, libFilePath);
if (zipFilePath != null) {
sLibraryWasLoadedFromApk = true;
}
- Linker.loadLibrary(zipFilePath, libFilePath);
}
// The WebView requires the Command Line to be switched over before
@@ -380,11 +392,13 @@
assert Linker.isUsed();
if (sLibraryWasLoadedFromApk) {
- return LibraryLoadFromApkStatusCodes.SUCCESSFUL;
+ return sMapApkWithExecPermission
+ ? LibraryLoadFromApkStatusCodes.SUCCESSFUL
+ : LibraryLoadFromApkStatusCodes.USED_NO_MAP_EXEC_SUPPORT_FALLBACK;
}
- if (!sLibraryWasAlignedInApk) {
- return LibraryLoadFromApkStatusCodes.NOT_ALIGNED;
+ if (!sLibraryIsMappableInApk) {
+ return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK;
}
if (context == null) {
@@ -392,7 +406,7 @@
return LibraryLoadFromApkStatusCodes.UNKNOWN;
}
- return Linker.checkLibraryLoadFromApkSupport(context.getApplicationInfo().sourceDir)
+ return sMapApkWithExecPermission
? LibraryLoadFromApkStatusCodes.SUPPORTED
: LibraryLoadFromApkStatusCodes.NOT_SUPPORTED;
}
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 67e5f83..d58d1fc 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
@@ -798,6 +798,19 @@
}
/**
+ * Enable the fallback due to lack of support for mapping the APK file with
+ * executable permission (see crbug.com/398425).
+ */
+ public static void enableNoMapExecSupportFallback() {
+ synchronized (Linker.class) {
+ ensureInitializedLocked();
+
+ if (DEBUG) Log.i(TAG, "Enabling no map executable support fallback");
+ nativeEnableNoMapExecSupportFallback();
+ }
+ }
+
+ /**
* Determine whether a library is the linker library. Also deal with the
* component build that adds a .cr suffix to the name.
*/
@@ -812,46 +825,50 @@
* @return the library path.
*/
public static String getLibraryFilePathInZipFile(String library) throws FileNotFoundException {
- String path = nativeGetLibraryFilePathInZipFile(library);
- if (path.equals("")) {
- throw new FileNotFoundException(
- "Failed to retrieve path in zip file for library " + library);
+ synchronized (Linker.class) {
+ ensureInitializedLocked();
+
+ String path = nativeGetLibraryFilePathInZipFile(library);
+ if (path.equals("")) {
+ throw new FileNotFoundException(
+ "Failed to retrieve path in zip file for library " + library);
+ }
+ return path;
}
- return path;
}
/**
- * Check whether the device supports loading a library directly from the APK file.
+ * Check whether the device supports mapping the APK file with executable permission.
*
* @param apkFile Filename of the APK.
* @return true if supported.
*/
- public static boolean checkLibraryLoadFromApkSupport(String apkFile) {
+ public static boolean checkMapExecSupport(String apkFile) {
assert apkFile != null;
synchronized (Linker.class) {
ensureInitializedLocked();
- if (DEBUG) Log.i(TAG, "checkLibraryLoadFromApkSupported: " + apkFile);
- boolean supported = nativeCheckLibraryLoadFromApkSupport(apkFile);
- if (DEBUG) Log.i(TAG, "Loading a library directly from the APK file "
+ if (DEBUG) Log.i(TAG, "checkMapExecSupport: " + apkFile);
+ boolean supported = nativeCheckMapExecSupport(apkFile);
+ if (DEBUG) Log.i(TAG, "Mapping the APK file with executable permission "
+ (supported ? "" : "NOT ") + "supported");
return supported;
}
}
/**
- * Check whether a library is page aligned in the APK file.
+ * Check whether a library is page aligned and uncompressed in the APK file.
*
* @param apkFile Filename of the APK.
* @param library The library's base name.
- * @return true if page aligned.
+ * @return true if page aligned and uncompressed.
*/
- public static boolean checkLibraryAlignedInApk(String apkFile, String library) {
+ public static boolean checkLibraryIsMappableInApk(String apkFile, String library) {
synchronized (Linker.class) {
ensureInitializedLocked();
- if (DEBUG) Log.i(TAG, "checkLibraryAlignedInApk: " + apkFile + ", " + library);
- boolean aligned = nativeCheckLibraryAlignedInApk(apkFile, library);
+ if (DEBUG) Log.i(TAG, "checkLibraryIsMappableInApk: " + apkFile + ", " + library);
+ boolean aligned = nativeCheckLibraryIsMappableInApk(apkFile, library);
if (DEBUG) Log.i(TAG, library + " is " + (aligned ? "" : "NOT ")
+ "page aligned in " + apkFile);
return aligned;
@@ -909,6 +926,12 @@
LibInfo libInfo);
/**
+ * Native method used to enable the fallback due to lack of support for
+ * mapping the APK file with executable permission.
+ */
+ private static native void nativeEnableNoMapExecSupportFallback();
+
+ /**
* Native method used to create a shared RELRO section.
* If the library was already loaded at the same address using
* nativeLoadLibrary(), this creates the RELRO for it. Otherwise,
@@ -964,22 +987,23 @@
private static native String nativeGetLibraryFilePathInZipFile(String library);
/**
- * Native method which checks whether the device supports loading a library
- * directly from the APK file.
+ * Native method which checks whether the device supports mapping the APK file
+ * with executable permission.
*
* @param apkFile Filename of the APK.
* @return true if supported.
*/
- private static native boolean nativeCheckLibraryLoadFromApkSupport(String apkFile);
+ private static native boolean nativeCheckMapExecSupport(String apkFile);
/**
- * Native method which checks whether a library is page aligned in the APK file.
+ * Native method which checks whether a library is page aligned and
+ * uncompressed in the APK file.
*
* @param apkFile Filename of the APK.
* @param library The library's base name.
- * @return true if page aligned.
+ * @return true if page aligned and uncompressed.
*/
- private static native boolean nativeCheckLibraryAlignedInApk(String apkFile, String library);
+ private static native boolean nativeCheckLibraryIsMappableInApk(String apkFile, String library);
/**
* Record information for a given library.
diff --git a/base/android/library_loader/library_load_from_apk_status_codes.h b/base/android/library_loader/library_load_from_apk_status_codes.h
index 21f40bc..f99eebc 100644
--- a/base/android/library_loader/library_load_from_apk_status_codes.h
+++ b/base/android/library_loader/library_load_from_apk_status_codes.h
@@ -10,6 +10,8 @@
namespace {
+// This enum must be kept in sync with the LibraryLoadFromApkStatus enum in
+// tools/metrics/histograms/histograms.xml.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
enum LibraryLoadFromApkStatusCodes {
// The loader was unable to determine whether the functionality is supported.
@@ -24,11 +26,16 @@
// The Chromium library was successfully loaded directly from the APK file.
LIBRARY_LOAD_FROM_APK_STATUS_CODES_SUCCESSFUL = 3,
- // The Chromium library was not page aligned in the APK file.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_NOT_ALIGNED = 4,
+ // The Chromium library was successfully loaded using the unpack library
+ // fallback because it was compressed or not page aligned in the APK file.
+ LIBRARY_LOAD_FROM_APK_STATUS_CODES_USED_UNPACK_LIBRARY_FALLBACK = 4,
+
+ // The Chromium library was successfully loaded using the no map executable
+ // support fallback.
+ LIBRARY_LOAD_FROM_APK_STATUS_CODES_USED_NO_MAP_EXEC_SUPPORT_FALLBACK = 5,
// End sentinel.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX = 5,
+ LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX = 6,
};
} // namespace
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 2b5a07d..b3ed651 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -386,6 +386,17 @@
static_cast<size_t>(load_address), lib_info_obj, opener);
}
+// Enable the fallback due to lack of support for mapping the APK file with
+// executable permission in the crazy linker.
+//
+// |env| is the current JNI environment handle and is ignored here.
+// |clazz| is the static class handle for org.chromium.base.Linker,
+// and is ignored here.
+void EnableNoMapExecSupportFallback(JNIEnv* env, jclass clazz) {
+ crazy_context_t* context = GetCrazyContext();
+ crazy_context_set_no_map_exec_support_fallback_enabled(context, true);
+}
+
// Class holding the Java class and method ID for the Java side Linker
// postCallbackOnMainThread method.
struct JavaCallbackBindings_class {
@@ -598,15 +609,14 @@
return env->NewStringUTF(buffer);
}
-// Check whether the device supports loading a library directly from the APK
-// file.
+// Check whether the device supports mapping the APK file with executable
+// permission.
//
// |env| is the current JNI environment handle.
// |clazz| is the static class handle which is not used here.
// |apkfile_name| is the filename of the APK.
// Returns true if supported.
-jboolean CheckLibraryLoadFromApkSupport(JNIEnv* env, jclass clazz,
- jstring apkfile_name) {
+jboolean CheckMapExecSupport(JNIEnv* env, jclass clazz, jstring apkfile_name) {
String apkfile_name_str(env, apkfile_name);
const char* apkfile_name_c_str = apkfile_name_str.c_str();
@@ -635,27 +645,28 @@
return status;
}
-// Check whether a library is page aligned in the APK file.
+// Check whether a library is page aligned and uncompressed in the APK file.
//
// |env| is the current JNI environment handle.
// |clazz| is the static class handle which is not used here.
// |apkfile_name| is the filename of the APK.
// |library_name| is the library base name.
-// Returns true if page aligned.
-jboolean CheckLibraryAlignedInApk(JNIEnv* env, jclass clazz,
- jstring apkfile_name, jstring library_name) {
+// Returns true if page aligned and uncompressed.
+jboolean CheckLibraryIsMappableInApk(JNIEnv* env, jclass clazz,
+ jstring apkfile_name,
+ jstring library_name) {
String apkfile_name_str(env, apkfile_name);
const char* apkfile_name_c_str = apkfile_name_str.c_str();
String library_name_str(env, library_name);
const char* library_name_c_str = library_name_str.c_str();
- LOG_INFO("%s: Checking if %s is page-aligned in %s\n", __FUNCTION__,
- library_name_c_str, apkfile_name_c_str);
- jboolean aligned = crazy_linker_check_library_aligned_in_zip_file(
+ LOG_INFO("%s: Checking if %s is page-aligned and uncompressed in %s\n",
+ __FUNCTION__, library_name_c_str, apkfile_name_c_str);
+ jboolean mappable = crazy_linker_check_library_is_mappable_in_zip_file(
apkfile_name_c_str, library_name_c_str) == CRAZY_STATUS_SUCCESS;
LOG_INFO("%s: %s\n", __FUNCTION__, aligned ? "Aligned" : "NOT aligned");
- return aligned;
+ return mappable;
}
const JNINativeMethod kNativeMethods[] = {
@@ -676,6 +687,11 @@
")"
"Z",
reinterpret_cast<void*>(&LoadLibraryInZipFile)},
+ {"nativeEnableNoMapExecSupportFallback",
+ "("
+ ")"
+ "V",
+ reinterpret_cast<void*>(&EnableNoMapExecSupportFallback)},
{"nativeRunCallbackOnUiThread",
"("
"J"
@@ -714,19 +730,19 @@
")"
"Ljava/lang/String;",
reinterpret_cast<void*>(&GetLibraryFilePathInZipFile)},
- {"nativeCheckLibraryLoadFromApkSupport",
+ {"nativeCheckMapExecSupport",
"("
"Ljava/lang/String;"
")"
"Z",
- reinterpret_cast<void*>(&CheckLibraryLoadFromApkSupport)},
- {"nativeCheckLibraryAlignedInApk",
+ reinterpret_cast<void*>(&CheckMapExecSupport)},
+ {"nativeCheckLibraryIsMappableInApk",
"("
"Ljava/lang/String;"
"Ljava/lang/String;"
")"
"Z",
- reinterpret_cast<void*>(&CheckLibraryAlignedInApk)}, };
+ reinterpret_cast<void*>(&CheckLibraryIsMappableInApk)}, };
} // namespace
diff --git a/base/file_version_info_win.cc b/base/file_version_info_win.cc
index 46b0581..ca3e4b1 100644
--- a/base/file_version_info_win.cc
+++ b/base/file_version_info_win.cc
@@ -9,7 +9,6 @@
#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/path_service.h"
#include "base/threading/thread_restrictions.h"
using base::FilePath;
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index d86d9bc..b8c0eeb 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -59,7 +59,7 @@
namespace base {
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
namespace {
#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
@@ -348,7 +348,7 @@
return success;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
bool PathExists(const FilePath& path) {
ThreadRestrictions::AssertIOAllowed();
@@ -360,7 +360,7 @@
return access(path.value().c_str(), F_OK) == 0;
}
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
bool PathIsWritable(const FilePath& path) {
ThreadRestrictions::AssertIOAllowed();
return access(path.value().c_str(), W_OK) == 0;
@@ -373,7 +373,7 @@
return S_ISDIR(file_info.st_mode);
return false;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
bool ReadFromFD(int fd, char* buffer, size_t bytes) {
size_t total_read = 0;
@@ -387,7 +387,7 @@
return total_read == bytes;
}
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
bool CreateSymbolicLink(const FilePath& target_path,
const FilePath& symlink_path) {
DCHECK(!symlink_path.empty());
@@ -928,5 +928,5 @@
} // namespace internal
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
} // namespace base
diff --git a/base/linux_util.cc b/base/linux_util.cc
index 29e1980..d6cd504 100644
--- a/base/linux_util.cc
+++ b/base/linux_util.cc
@@ -18,7 +18,6 @@
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
-#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
diff --git a/base/memory/singleton_unittest.cc b/base/memory/singleton_unittest.cc
index 41bd75c..0e9ecdc 100644
--- a/base/memory/singleton_unittest.cc
+++ b/base/memory/singleton_unittest.cc
@@ -4,7 +4,6 @@
#include "base/at_exit.h"
#include "base/memory/singleton.h"
-#include "base/path_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index f1d0d3b..01402d0 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -100,7 +100,7 @@
#if defined(OS_IOS)
typedef MessagePumpIOSForIO MessagePumpForIO;
-#elif defined(OS_NACL) && !defined(__native_client_nonsfi__)
+#elif defined(OS_NACL_SFI)
typedef MessagePumpDefault MessagePumpForIO;
#elif defined(OS_POSIX)
typedef MessagePumpLibevent MessagePumpForIO;
@@ -676,7 +676,7 @@
//------------------------------------------------------------------------------
// MessageLoopForIO
-#if !defined(OS_NACL) || defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_SFI)
void MessageLoopForIO::AddIOObserver(
MessageLoopForIO::IOObserver* io_observer) {
ToPumpIO(pump_.get())->AddIOObserver(io_observer);
@@ -714,6 +714,6 @@
}
#endif
-#endif // !defined(OS_NACL) || defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_SFI)
} // namespace base
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index b781711..47df69a 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -596,7 +596,7 @@
return loop && loop->type() == MessageLoop::TYPE_IO;
}
-#if !defined(OS_NACL) || defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_SFI)
#if defined(OS_WIN)
typedef MessagePumpForIO::IOHandler IOHandler;
@@ -642,7 +642,7 @@
FileDescriptorWatcher *controller,
Watcher *delegate);
#endif // defined(OS_IOS) || defined(OS_POSIX)
-#endif // !defined(OS_NACL) || defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_SFI)
};
// Do not add any member variables to MessageLoopForIO! This is important b/c
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index c82f33d..7efca7a 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -67,6 +67,7 @@
bool FieldTrial::enable_benchmarking_ = false;
const char FieldTrialList::kPersistentStringSeparator('/');
+const char FieldTrialList::kActivationMarker('*');
int FieldTrialList::kNoExpirationYear = 0;
//------------------------------------------------------------------------------
@@ -421,7 +422,18 @@
return false;
if (group_name_end == trials_string.npos)
group_name_end = trials_string.length();
- std::string name(trials_string, next_item, name_end - next_item);
+
+ // Verify if the trial should be activated or not.
+ std::string name;
+ bool force_activation = false;
+ if (trials_string[next_item] == kActivationMarker) {
+ // Name cannot be only the indicator.
+ if (name_end - next_item == 1)
+ return false;
+ next_item++;
+ force_activation = true;
+ }
+ name.append(trials_string, next_item, name_end - next_item);
std::string group_name(trials_string, name_end + 1,
group_name_end - name_end - 1);
next_item = group_name_end + 1;
@@ -432,7 +444,7 @@
FieldTrial* trial = CreateFieldTrial(name, group_name);
if (!trial)
return false;
- if (mode == ACTIVATE_TRIALS) {
+ if (mode == ACTIVATE_TRIALS || force_activation) {
// Call |group()| to mark the trial as "used" and notify observers, if
// any. This is useful to ensure that field trials created in child
// processes are properly reported in crash reports.
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 25ee0c1..e2e5439 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -291,7 +291,8 @@
class BASE_EXPORT FieldTrialList {
public:
// Specifies whether field trials should be activated (marked as "used"), when
- // created using |CreateTrialsFromString()|.
+ // created using |CreateTrialsFromString()|. Has no effect on trials that are
+ // prefixed with |kActivationMarker|, which will always be activated."
enum FieldTrialActivationMode {
DONT_ACTIVATE_TRIALS,
ACTIVATE_TRIALS,
@@ -302,6 +303,10 @@
// second process to mimic our state (i.e., provide the same group name).
static const char kPersistentStringSeparator; // Currently a slash.
+ // Define a marker character to be used as a prefix to a trial name on the
+ // command line which forces its activation.
+ static const char kActivationMarker; // Currently an asterisk.
+
// Year that is guaranteed to not be expired when instantiating a field trial
// via |FactoryGetFieldTrial()|. Set to two years from the build date.
static int kNoExpirationYear;
@@ -412,9 +417,10 @@
// used in a non-browser process, to carry randomly selected state in a
// browser process into this non-browser process, but could also be invoked
// through a command line argument to the browser process. The created field
- // trials are marked as "used" for the purposes of active trial reporting if
- // |mode| is ACTIVATE_TRIALS. Trial names in |ignored_trial_names| are ignored
- // when parsing |prior_trials|.
+ // trials are all marked as "used" for the purposes of active trial reporting
+ // if |mode| is ACTIVATE_TRIALS, otherwise each trial will be marked as "used"
+ // if it is prefixed with |kActivationMarker|. Trial names in
+ // |ignored_trial_names| are ignored when parsing |prior_trials|.
static bool CreateTrialsFromString(
const std::string& prior_trials,
FieldTrialActivationMode mode,
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
index 1ed3f89..ce95c2a 100644
--- a/base/metrics/field_trial_unittest.cc
+++ b/base/metrics/field_trial_unittest.cc
@@ -428,6 +428,12 @@
EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
"noname, only group/", FieldTrialList::DONT_ACTIVATE_TRIALS,
std::set<std::string>()));
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
+ "/emptyname", FieldTrialList::DONT_ACTIVATE_TRIALS,
+ std::set<std::string>()));
+ EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
+ "*/emptyname", FieldTrialList::DONT_ACTIVATE_TRIALS,
+ std::set<std::string>()));
}
TEST_F(FieldTrialTest, DuplicateRestore) {
@@ -490,6 +496,23 @@
EXPECT_EQ("zyx", active_groups[1].group_name);
}
+TEST_F(FieldTrialTest, CreateTrialsFromStringForceActivation) {
+ ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
+ ASSERT_FALSE(FieldTrialList::TrialExists("def"));
+ ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
+ ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
+ "*Abc/cba/def/fed/*Xyz/zyx/", FieldTrialList::DONT_ACTIVATE_TRIALS,
+ std::set<std::string>()));
+
+ FieldTrial::ActiveGroups active_groups;
+ FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
+ ASSERT_EQ(2U, active_groups.size());
+ EXPECT_EQ("Abc", active_groups[0].trial_name);
+ EXPECT_EQ("cba", active_groups[0].group_name);
+ EXPECT_EQ("Xyz", active_groups[1].trial_name);
+ EXPECT_EQ("zyx", active_groups[1].group_name);
+}
+
TEST_F(FieldTrialTest, CreateTrialsFromStringActiveObserver) {
ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
diff --git a/base/posix/unix_domain_socket_linux.cc b/base/posix/unix_domain_socket_linux.cc
index 20a5944..203285b 100644
--- a/base/posix/unix_domain_socket_linux.cc
+++ b/base/posix/unix_domain_socket_linux.cc
@@ -17,13 +17,13 @@
#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
#include <sys/uio.h>
#endif
const size_t UnixDomainSocket::kMaxFileDescriptors = 16;
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// Creates a connected pair of UNIX-domain SOCK_SEQPACKET sockets, and passes
// ownership of the newly allocated file descriptors to |one| and |two|.
// Returns true on success.
@@ -41,7 +41,7 @@
const int enable = 1;
return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
// static
bool UnixDomainSocket::SendMsg(int fd,
@@ -113,7 +113,7 @@
const size_t kControlBufferSize =
CMSG_SPACE(sizeof(int) * kMaxFileDescriptors)
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// The PNaCl toolchain for Non-SFI binary build does not support ucred.
+ CMSG_SPACE(sizeof(struct ucred))
#endif
@@ -141,7 +141,7 @@
wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
wire_fds_len = payload_len / sizeof(int);
}
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// The PNaCl toolchain for Non-SFI binary build does not support
// SCM_CREDENTIALS.
if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -154,16 +154,12 @@
}
}
-#if !defined(__native_client_nonsfi__)
- // The PNaCl toolchain for Non-SFI binary build does not support
- // MSG_TRUNC or MSG_CTRUNC.
if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
for (unsigned i = 0; i < wire_fds_len; ++i)
close(wire_fds[i]);
errno = EMSGSIZE;
return -1;
}
-#endif
if (wire_fds) {
for (unsigned i = 0; i < wire_fds_len; ++i)
@@ -184,7 +180,7 @@
return r;
}
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// static
ssize_t UnixDomainSocket::SendRecvMsg(int fd,
uint8_t* reply,
@@ -242,4 +238,4 @@
return reply_len;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
diff --git a/base/posix/unix_domain_socket_linux.h b/base/posix/unix_domain_socket_linux.h
index 5281875..142cb14 100644
--- a/base/posix/unix_domain_socket_linux.h
+++ b/base/posix/unix_domain_socket_linux.h
@@ -21,12 +21,12 @@
// Maximum number of file descriptors that can be read by RecvMsg().
static const size_t kMaxFileDescriptors;
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// Use to enable receiving process IDs in RecvMsgWithPid. Should be called on
// the receiving socket (i.e., the socket passed to RecvMsgWithPid). Returns
// true if successful.
static bool EnableReceiveProcessId(int fd);
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
// Use sendmsg to write the given msg and include a vector of file
// descriptors. Returns true if successful.
@@ -52,7 +52,7 @@
ScopedVector<base::ScopedFD>* fds,
base::ProcessId* pid);
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
// Perform a sendmsg/recvmsg pair.
// 1. This process creates a UNIX SEQPACKET socketpair. Using
// connection-oriented sockets (SEQPACKET or STREAM) is critical here,
@@ -85,7 +85,7 @@
int recvmsg_flags,
int* result_fd,
const Pickle& request);
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
private:
// Similar to RecvMsg, but allows to specify |flags| for recvmsg(2).
static ssize_t RecvMsgWithFlags(int fd,
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index b02453c..d17e990 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -22,7 +22,7 @@
namespace {
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
bool WaitpidWithTimeout(ProcessHandle handle,
int* status,
base::TimeDelta wait) {
@@ -84,7 +84,7 @@
return ret_pid > 0;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
bool can_block,
@@ -132,7 +132,7 @@
} // namespace
-#if !defined(__native_client_nonsfi__)
+#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.
@@ -194,7 +194,7 @@
DPLOG(ERROR) << "Unable to terminate process group " << process_group_id;
return result;
}
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
return GetTerminationStatusImpl(handle, false /* can_block */, exit_code);
@@ -210,7 +210,7 @@
return GetTerminationStatusImpl(handle, true /* can_block */, exit_code);
}
-#if !defined(__native_client_nonsfi__)
+#if !defined(OS_NACL_NONSFI)
bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
int status;
if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
@@ -483,6 +483,6 @@
}
#endif // !defined(OS_MACOSX)
-#endif // !defined(__native_client_nonsfi__)
+#endif // !defined(OS_NACL_NONSFI)
} // namespace base
diff --git a/base/profiler/scoped_tracker.h b/base/profiler/scoped_tracker.h
index a188557..f83654e 100644
--- a/base/profiler/scoped_tracker.h
+++ b/base/profiler/scoped_tracker.h
@@ -19,6 +19,21 @@
// ScopedTracker instruments a region within the code if the instrumentation is
// enabled. It can be used, for example, to find out if a source of jankiness is
// inside the instrumented code region.
+// Details:
+// 1. This class creates a task (like ones created by PostTask calls or IPC
+// message handlers). This task can be seen in chrome://profiler and is sent as
+// a part of profiler data to the UMA server. See profiler_event.proto.
+// 2. That task's lifetime is same as the lifetime of the ScopedTracker
+// instance.
+// 3. The execution time associated with the task is the wallclock time between
+// its constructor and destructor, minus wallclock times of directly nested
+// tasks.
+// 4. Task creation that this class utilizes is highly optimized.
+// 5. The class doesn't create a task unless this was enabled for the current
+// process. Search for ScopedTracker::Enable for the current list of processes
+// and channels where it's activated.
+// 6. The class is designed for temporarily instrumenting code to find
+// performance problems, after which the instrumentation must be removed.
class BASE_EXPORT ScopedTracker {
public:
ScopedTracker(const Location& location);
diff --git a/base/sys_info.cc b/base/sys_info.cc
index 0b3b317..cb93480 100644
--- a/base/sys_info.cc
+++ b/base/sys_info.cc
@@ -44,6 +44,12 @@
}
#endif
+#if !defined(OS_MACOSX) || defined(OS_IOS)
+std::string SysInfo::HardwareModelName() {
+ return std::string();
+}
+#endif
+
// static
int64 SysInfo::Uptime() {
// This code relies on an implementation detail of TimeTicks::Now() - that
diff --git a/base/sys_info.h b/base/sys_info.h
index d24acdf..660343d 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -51,6 +51,12 @@
// Returns system uptime in milliseconds.
static int64 Uptime();
+ // Returns a descriptive string for the current machine model or an empty
+ // string if machime model is unknown or an error occured.
+ // e.g. MacPro1,1 on Mac.
+ // Only implemented on OS X, will return an empty string on other platforms.
+ static std::string HardwareModelName();
+
// Returns the name of the host operating system.
static std::string OperatingSystemName();
diff --git a/base/sys_info_mac.cc b/base/sys_info_mac.cc
index 57e1f83..18df624 100644
--- a/base/sys_info_mac.cc
+++ b/base/sys_info_mac.cc
@@ -85,4 +85,12 @@
return std::string();
}
+std::string SysInfo::HardwareModelName() {
+ char model[256];
+ size_t len = sizeof(model);
+ if (sysctlbyname("hw.model", model, &len, NULL, 0) == 0)
+ return std::string(model, 0, len);
+ return std::string();
+}
+
} // namespace base
diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc
index 29409ee..15ae098 100644
--- a/base/sys_info_unittest.cc
+++ b/base/sys_info_unittest.cc
@@ -65,6 +65,13 @@
EXPECT_GT(up_time_2, up_time_1);
}
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+TEST_F(SysInfoTest, HardwareModelName) {
+ std::string hardware_model = base::SysInfo::HardwareModelName();
+ EXPECT_FALSE(hardware_model.empty());
+}
+#endif
+
#if defined(OS_CHROMEOS)
TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) {
diff --git a/base/timer/timer.cc b/base/timer/timer.cc
index 1916ccc..11f73ca 100644
--- a/base/timer/timer.cc
+++ b/base/timer/timer.cc
@@ -93,6 +93,12 @@
return delay_;
}
+void Timer::SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) {
+ // Do not allow changing the task runner once something has been scheduled.
+ DCHECK_EQ(thread_id_, 0);
+ task_runner_.swap(task_runner);
+}
+
void Timer::Start(const tracked_objects::Location& posted_from,
TimeDelta delay,
const base::Closure& user_task) {
@@ -146,12 +152,12 @@
is_running_ = true;
scheduled_task_ = new BaseTimerTaskInternal(this);
if (delay > TimeDelta::FromMicroseconds(0)) {
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(posted_from_,
+ GetTaskRunner()->PostDelayedTask(posted_from_,
base::Bind(&BaseTimerTaskInternal::Run, base::Owned(scheduled_task_)),
delay);
scheduled_run_time_ = desired_run_time_ = TimeTicks::Now() + delay;
} else {
- ThreadTaskRunnerHandle::Get()->PostTask(posted_from_,
+ GetTaskRunner()->PostTask(posted_from_,
base::Bind(&BaseTimerTaskInternal::Run, base::Owned(scheduled_task_)));
scheduled_run_time_ = desired_run_time_ = TimeTicks();
}
@@ -161,6 +167,10 @@
thread_id_ = static_cast<int>(PlatformThread::CurrentId());
}
+scoped_refptr<SingleThreadTaskRunner> Timer::GetTaskRunner() {
+ return task_runner_.get() ? task_runner_ : ThreadTaskRunnerHandle::Get();
+}
+
void Timer::AbandonScheduledTask() {
DCHECK(thread_id_ == 0 ||
thread_id_ == static_cast<int>(PlatformThread::CurrentId()));
diff --git a/base/timer/timer.h b/base/timer/timer.h
index 4ef2f45..7e2c1d4 100644
--- a/base/timer/timer.h
+++ b/base/timer/timer.h
@@ -60,6 +60,7 @@
namespace base {
class BaseTimerTaskInternal;
+class SingleThreadTaskRunner;
//-----------------------------------------------------------------------------
// This class wraps MessageLoop::PostDelayedTask to manage delayed and repeating
@@ -87,6 +88,10 @@
// Returns the current delay for this timer.
virtual TimeDelta GetCurrentDelay() const;
+ // Set the task runner on which the task should be scheduled. This method can
+ // only be called before any tasks have been scheduled.
+ virtual void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
+
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call the given |user_task|.
virtual void Start(const tracked_objects::Location& posted_from,
@@ -128,6 +133,11 @@
// and desired_run_time_ are reset to Now() + delay.
void PostNewScheduledTask(TimeDelta delay);
+ // Returns the task runner on which the task should be scheduled. If the
+ // corresponding task_runner_ field is null, the task runner for the current
+ // thread is returned.
+ scoped_refptr<SingleThreadTaskRunner> GetTaskRunner();
+
// Disable scheduled_task_ and abandon it so that it no longer refers back to
// this object.
void AbandonScheduledTask();
@@ -145,6 +155,10 @@
// RunScheduledTask() at scheduled_run_time_.
BaseTimerTaskInternal* scheduled_task_;
+ // The task runner on which the task should be scheduled. If it is null, the
+ // task runner for the current thread should be used.
+ scoped_refptr<SingleThreadTaskRunner> task_runner_;
+
// Location in user code.
tracked_objects::Location posted_from_;
// Delay requested by user.
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
index 0fb2b45..1cbccd1 100644
--- a/base/timer/timer_unittest.cc
+++ b/base/timer/timer_unittest.cc
@@ -4,10 +4,12 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/test/test_simple_task_runner.h"
#include "base/timer/timer.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
+using base::SingleThreadTaskRunner;
namespace {
@@ -26,20 +28,32 @@
public:
explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10)
: did_run_(did_run),
- delay_ms_(milliseconds) {
+ delay_ms_(milliseconds),
+ quit_message_loop_(true) {
}
+
void Start() {
timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this,
&OneShotTimerTester::Run);
}
+
+ void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) {
+ quit_message_loop_ = false;
+ timer_.SetTaskRunner(task_runner);
+ }
+
private:
void Run() {
*did_run_ = true;
- base::MessageLoop::current()->QuitWhenIdle();
+ if (quit_message_loop_) {
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
}
+
bool* did_run_;
base::OneShotTimer<OneShotTimerTester> timer_;
const unsigned delay_ms_;
+ bool quit_message_loop_;
};
class OneShotSelfDeletingTimerTester {
@@ -48,16 +62,19 @@
did_run_(did_run),
timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) {
}
+
void Start() {
timer_->Start(FROM_HERE, TimeDelta::FromMilliseconds(10), this,
&OneShotSelfDeletingTimerTester::Run);
}
+
private:
void Run() {
*did_run_ = true;
timer_.reset();
base::MessageLoop::current()->QuitWhenIdle();
}
+
bool* did_run_;
scoped_ptr<base::OneShotTimer<OneShotSelfDeletingTimerTester> > timer_;
};
@@ -71,6 +88,7 @@
void Start() {
timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
}
+
private:
void Run() {
if (--counter_ == 0) {
@@ -79,6 +97,7 @@
base::MessageLoop::current()->QuitWhenIdle();
}
}
+
bool* did_run_;
int counter_;
TimeDelta delay_;
@@ -310,6 +329,20 @@
}
}
+TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner =
+ new base::TestSimpleTaskRunner();
+
+ bool did_run = false;
+ OneShotTimerTester f(&did_run);
+ f.SetTaskRunner(task_runner);
+ f.Start();
+
+ EXPECT_FALSE(did_run);
+ task_runner->RunUntilIdle();
+ EXPECT_TRUE(did_run);
+}
+
TEST(TimerTest, RepeatingTimer) {
for (int i = 0; i < kNumTestingMessageLoops; i++) {
RunTest_RepeatingTimer(testing_message_loops[i],
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index 4fe8851..c69fada 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -54,18 +54,27 @@
// problem with its presence).
static const bool kAllowAlternateTimeSourceHandling = true;
+// Possible states of the profiler timing enabledness.
+enum {
+ UNDEFINED_TIMING,
+ ENABLED_TIMING,
+ DISABLED_TIMING,
+};
+
+// State of the profiler timing enabledness.
+base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING;
+
+// Returns whether profiler timing is enabled. The default is true, but this may
+// be overridden by a command-line flag. Some platforms may programmatically set
+// this command-line flag to the "off" value if it's not specified.
+// This in turn can be overridden by explicitly calling
+// ThreadData::EnableProfilerTiming, say, based on a field trial.
inline bool IsProfilerTimingEnabled() {
- enum {
- UNDEFINED_TIMING,
- ENABLED_TIMING,
- DISABLED_TIMING,
- };
- static base::subtle::Atomic32 timing_enabled = UNDEFINED_TIMING;
- // Reading |timing_enabled| is done without barrier because multiple
- // initialization is not an issue while the barrier can be relatively costly
- // given that this method is sometimes called in a tight loop.
+ // Reading |g_profiler_timing_enabled| is done without barrier because
+ // multiple initialization is not an issue while the barrier can be relatively
+ // costly given that this method is sometimes called in a tight loop.
base::subtle::Atomic32 current_timing_enabled =
- base::subtle::NoBarrier_Load(&timing_enabled);
+ base::subtle::NoBarrier_Load(&g_profiler_timing_enabled);
if (current_timing_enabled == UNDEFINED_TIMING) {
if (!CommandLine::InitializedForCurrentProcess())
return true;
@@ -75,7 +84,8 @@
switches::kProfilerTimingDisabledValue)
? DISABLED_TIMING
: ENABLED_TIMING;
- base::subtle::NoBarrier_Store(&timing_enabled, current_timing_enabled);
+ base::subtle::NoBarrier_Store(&g_profiler_timing_enabled,
+ current_timing_enabled);
}
return current_timing_enabled == ENABLED_TIMING;
}
@@ -775,6 +785,11 @@
}
// static
+void ThreadData::EnableProfilerTiming() {
+ base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING);
+}
+
+// static
TrackedTime ThreadData::Now() {
if (kAllowAlternateTimeSourceHandling && now_function_)
return TrackedTime::FromMilliseconds((*now_function_)());
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 222f581..50bea47 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -466,6 +466,9 @@
// relationships can be (optionally) calculated.
static void PrepareForStartOfRun(const Births* parent);
+ // Enables profiler timing.
+ static void EnableProfilerTiming();
+
// Provide a time function that does nothing (runs fast) when we don't have
// the profiler enabled. It will generally be optimized away when it is
// ifdef'ed to be small enough (allowing the profiler to be "compiled out" of
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 21b78fa..f46242d 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -119,12 +119,14 @@
static bool g_crash_on_process_detach = false;
-void GetNonClientMetrics(NONCLIENTMETRICS* metrics) {
+void GetNonClientMetrics(NONCLIENTMETRICS_XP* metrics) {
DCHECK(metrics);
metrics->cbSize = sizeof(*metrics);
- const bool success =
- !!SystemParametersInfo(
- SPI_GETNONCLIENTMETRICS, metrics->cbSize, metrics, 0);
+ const bool success = !!SystemParametersInfo(
+ SPI_GETNONCLIENTMETRICS,
+ metrics->cbSize,
+ reinterpret_cast<NONCLIENTMETRICS*>(metrics),
+ 0);
DCHECK(success);
}
diff --git a/base/win/win_util.h b/base/win/win_util.h
index 9439597..8513f62 100644
--- a/base/win/win_util.h
+++ b/base/win/win_util.h
@@ -33,10 +33,30 @@
struct _tagpropertykey;
typedef _tagpropertykey PROPERTYKEY;
+// This is the same as NONCLIENTMETRICS except that the
+// unused member |iPaddedBorderWidth| has been removed.
+struct NONCLIENTMETRICS_XP {
+ UINT cbSize;
+ int iBorderWidth;
+ int iScrollWidth;
+ int iScrollHeight;
+ int iCaptionWidth;
+ int iCaptionHeight;
+ LOGFONTW lfCaptionFont;
+ int iSmCaptionWidth;
+ int iSmCaptionHeight;
+ LOGFONTW lfSmCaptionFont;
+ int iMenuWidth;
+ int iMenuHeight;
+ LOGFONTW lfMenuFont;
+ LOGFONTW lfStatusFont;
+ LOGFONTW lfMessageFont;
+};
+
namespace base {
namespace win {
-BASE_EXPORT void GetNonClientMetrics(NONCLIENTMETRICS* metrics);
+BASE_EXPORT void GetNonClientMetrics(NONCLIENTMETRICS_XP* metrics);
// Returns the string representing the current user sid.
BASE_EXPORT bool GetUserSidString(std::wstring* user_sid);