0

Set svn:eol-style = LF on files in base from which it is missing

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1648 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
mmentovai@google.com
2008-09-02 18:20:34 +00:00
parent 844cbe038f
commit b2e972938c
15 changed files with 1063 additions and 1039 deletions

@@ -1,66 +1,66 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/at_exit.h" #include "base/at_exit.h"
#include "base/logging.h" #include "base/logging.h"
namespace base { namespace base {
// Keep a stack of registered AtExitManagers. We always operate on the most // Keep a stack of registered AtExitManagers. We always operate on the most
// recent, and we should never have more than one outside of testing, when we // recent, and we should never have more than one outside of testing, when we
// use the shadow version of the constructor. We don't protect this for // use the shadow version of the constructor. We don't protect this for
// thread-safe access, since it will only be modified in testing. // thread-safe access, since it will only be modified in testing.
static AtExitManager* g_top_manager = NULL; static AtExitManager* g_top_manager = NULL;
AtExitManager::AtExitManager() : next_manager_(NULL) { AtExitManager::AtExitManager() : next_manager_(NULL) {
DCHECK(!g_top_manager); DCHECK(!g_top_manager);
g_top_manager = this; g_top_manager = this;
} }
AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) { AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
DCHECK(shadow || !g_top_manager); DCHECK(shadow || !g_top_manager);
g_top_manager = this; g_top_manager = this;
} }
AtExitManager::~AtExitManager() { AtExitManager::~AtExitManager() {
if (!g_top_manager) { if (!g_top_manager) {
NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager"; NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
return; return;
} }
DCHECK(g_top_manager == this); DCHECK(g_top_manager == this);
ProcessCallbacksNow(); ProcessCallbacksNow();
g_top_manager = next_manager_; g_top_manager = next_manager_;
} }
// static // static
void AtExitManager::RegisterCallback(AtExitCallbackType func) { void AtExitManager::RegisterCallback(AtExitCallbackType func) {
if (!g_top_manager) { if (!g_top_manager) {
NOTREACHED() << "Tried to RegisterCallback without an AtExitManager"; NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
return; return;
} }
AutoLock lock(g_top_manager->lock_); AutoLock lock(g_top_manager->lock_);
g_top_manager->stack_.push(func); g_top_manager->stack_.push(func);
} }
// static // static
void AtExitManager::ProcessCallbacksNow() { void AtExitManager::ProcessCallbacksNow() {
if (!g_top_manager) { if (!g_top_manager) {
NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager"; NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager";
return; return;
} }
AutoLock lock(g_top_manager->lock_); AutoLock lock(g_top_manager->lock_);
while (!g_top_manager->stack_.empty()) { while (!g_top_manager->stack_.empty()) {
AtExitCallbackType func = g_top_manager->stack_.top(); AtExitCallbackType func = g_top_manager->stack_.top();
g_top_manager->stack_.pop(); g_top_manager->stack_.pop();
if (func) if (func)
func(); func();
} }
} }
} // namespace base } // namespace base

@@ -1,65 +1,65 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_AT_EXIT_H_ #ifndef BASE_AT_EXIT_H_
#define BASE_AT_EXIT_H_ #define BASE_AT_EXIT_H_
#include <stack> #include <stack>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/lock.h" #include "base/lock.h"
namespace base { namespace base {
// This class provides a facility similar to the CRT atexit(), except that // This class provides a facility similar to the CRT atexit(), except that
// we control when the callbacks are executed. Under Windows for a DLL they // we control when the callbacks are executed. Under Windows for a DLL they
// happen at a really bad time and under the loader lock. This facility is // happen at a really bad time and under the loader lock. This facility is
// mostly used by base::Singleton. // mostly used by base::Singleton.
// //
// The usage is simple. Early in the main() or WinMain() scope create an // The usage is simple. Early in the main() or WinMain() scope create an
// AtExitManager object on the stack: // AtExitManager object on the stack:
// int main(...) { // int main(...) {
// base::AtExitManager exit_manager; // base::AtExitManager exit_manager;
// //
// } // }
// When the exit_manager object goes out of scope, all the registered // When the exit_manager object goes out of scope, all the registered
// callbacks and singleton destructors will be called. // callbacks and singleton destructors will be called.
class AtExitManager { class AtExitManager {
protected: protected:
// This constructor will allow this instance of AtExitManager to be created // This constructor will allow this instance of AtExitManager to be created
// even if one already exists. This should only be used for testing! // even if one already exists. This should only be used for testing!
// AtExitManagers are kept on a global stack, and it will be removed during // AtExitManagers are kept on a global stack, and it will be removed during
// destruction. This allows you to shadow another AtExitManager. // destruction. This allows you to shadow another AtExitManager.
AtExitManager(bool shadow); AtExitManager(bool shadow);
public: public:
typedef void (*AtExitCallbackType)(); typedef void (*AtExitCallbackType)();
AtExitManager(); AtExitManager();
// The dtor calls all the registered callbacks. Do not try to register more // The dtor calls all the registered callbacks. Do not try to register more
// callbacks after this point. // callbacks after this point.
~AtExitManager(); ~AtExitManager();
// Registers the specified function to be called at exit. The prototype of // Registers the specified function to be called at exit. The prototype of
// the callback function is void func(). // the callback function is void func().
static void RegisterCallback(AtExitCallbackType func); static void RegisterCallback(AtExitCallbackType func);
// Calls the functions registered with RegisterCallback in LIFO order. It // Calls the functions registered with RegisterCallback in LIFO order. It
// is possible to register new callbacks after calling this function. // is possible to register new callbacks after calling this function.
static void ProcessCallbacksNow(); static void ProcessCallbacksNow();
private: private:
Lock lock_; Lock lock_;
std::stack<AtExitCallbackType> stack_; std::stack<AtExitCallbackType> stack_;
AtExitManager* next_manager_; // Stack of managers to allow shadowing. AtExitManager* next_manager_; // Stack of managers to allow shadowing.
DISALLOW_COPY_AND_ASSIGN(AtExitManager); DISALLOW_COPY_AND_ASSIGN(AtExitManager);
}; };
} // namespace base } // namespace base
#endif // BASE_AT_EXIT_H_ #endif // BASE_AT_EXIT_H_

@@ -1,69 +1,69 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/at_exit.h" #include "base/at_exit.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace { namespace {
// Don't test the global AtExitManager, because asking it to process its // Don't test the global AtExitManager, because asking it to process its
// AtExit callbacks can ruin the global state that other tests may depend on. // AtExit callbacks can ruin the global state that other tests may depend on.
class ShadowingAtExitManager : public base::AtExitManager { class ShadowingAtExitManager : public base::AtExitManager {
public: public:
ShadowingAtExitManager() : AtExitManager(true) {} ShadowingAtExitManager() : AtExitManager(true) {}
}; };
int g_test_counter_1 = 0; int g_test_counter_1 = 0;
int g_test_counter_2 = 0; int g_test_counter_2 = 0;
void IncrementTestCounter1() { void IncrementTestCounter1() {
++g_test_counter_1; ++g_test_counter_1;
} }
void IncrementTestCounter2() { void IncrementTestCounter2() {
++g_test_counter_2; ++g_test_counter_2;
} }
void ZeroTestCounters() { void ZeroTestCounters() {
g_test_counter_1 = 0; g_test_counter_1 = 0;
g_test_counter_2 = 0; g_test_counter_2 = 0;
} }
void ExpectCounter1IsZero() { void ExpectCounter1IsZero() {
EXPECT_EQ(0, g_test_counter_1); EXPECT_EQ(0, g_test_counter_1);
} }
} // namespace } // namespace
TEST(AtExitTest, Basic) { TEST(AtExitTest, Basic) {
ShadowingAtExitManager shadowing_at_exit_manager; ShadowingAtExitManager shadowing_at_exit_manager;
ZeroTestCounters(); ZeroTestCounters();
base::AtExitManager::RegisterCallback(&IncrementTestCounter1); base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2); base::AtExitManager::RegisterCallback(&IncrementTestCounter2);
base::AtExitManager::RegisterCallback(&IncrementTestCounter1); base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
EXPECT_EQ(0, g_test_counter_1); EXPECT_EQ(0, g_test_counter_1);
EXPECT_EQ(0, g_test_counter_2); EXPECT_EQ(0, g_test_counter_2);
base::AtExitManager::ProcessCallbacksNow(); base::AtExitManager::ProcessCallbacksNow();
EXPECT_EQ(2, g_test_counter_1); EXPECT_EQ(2, g_test_counter_1);
EXPECT_EQ(1, g_test_counter_2); EXPECT_EQ(1, g_test_counter_2);
} }
TEST(AtExitTest, LIFOOrder) { TEST(AtExitTest, LIFOOrder) {
ShadowingAtExitManager shadowing_at_exit_manager; ShadowingAtExitManager shadowing_at_exit_manager;
ZeroTestCounters(); ZeroTestCounters();
base::AtExitManager::RegisterCallback(&IncrementTestCounter1); base::AtExitManager::RegisterCallback(&IncrementTestCounter1);
base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero); base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero);
base::AtExitManager::RegisterCallback(&IncrementTestCounter2); base::AtExitManager::RegisterCallback(&IncrementTestCounter2);
EXPECT_EQ(0, g_test_counter_1); EXPECT_EQ(0, g_test_counter_1);
EXPECT_EQ(0, g_test_counter_2); EXPECT_EQ(0, g_test_counter_2);
base::AtExitManager::ProcessCallbacksNow(); base::AtExitManager::ProcessCallbacksNow();
EXPECT_EQ(1, g_test_counter_1); EXPECT_EQ(1, g_test_counter_1);
EXPECT_EQ(1, g_test_counter_2); EXPECT_EQ(1, g_test_counter_2);
} }

@@ -1,65 +1,65 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This is a low level implementation of atomic semantics for reference // This is a low level implementation of atomic semantics for reference
// counting. Please use base/ref_counted.h directly instead. // counting. Please use base/ref_counted.h directly instead.
#ifndef BASE_ATOMIC_REF_COUNT_H_ #ifndef BASE_ATOMIC_REF_COUNT_H_
#define BASE_ATOMIC_REF_COUNT_H_ #define BASE_ATOMIC_REF_COUNT_H_
#include "base/atomicops.h" #include "base/atomicops.h"
#include "base/basictypes.h" #include "base/basictypes.h"
namespace base { namespace base {
typedef base::subtle::Atomic32 AtomicRefCount; typedef base::subtle::Atomic32 AtomicRefCount;
// Increment a reference count by "increment", which must exceed 0. // Increment a reference count by "increment", which must exceed 0.
inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr, inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
AtomicRefCount increment) { AtomicRefCount increment) {
base::subtle::NoBarrier_AtomicIncrement(ptr, increment); base::subtle::NoBarrier_AtomicIncrement(ptr, increment);
} }
// Decrement a reference count by "decrement", which must exceed 0, // Decrement a reference count by "decrement", which must exceed 0,
// and return whether the result is non-zero. // and return whether the result is non-zero.
// Insert barriers to ensure that state written before the reference count // Insert barriers to ensure that state written before the reference count
// became zero will be visible to a thread that has just made the count zero. // became zero will be visible to a thread that has just made the count zero.
inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr, inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
AtomicRefCount decrement) { AtomicRefCount decrement) {
return base::subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0; return base::subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0;
} }
// Increment a reference count by 1. // Increment a reference count by 1.
inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) { inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
base::AtomicRefCountIncN(ptr, 1); base::AtomicRefCountIncN(ptr, 1);
} }
// Decrement a reference count by 1 and return whether the result is non-zero. // Decrement a reference count by 1 and return whether the result is non-zero.
// Insert barriers to ensure that state written before the reference count // Insert barriers to ensure that state written before the reference count
// became zero will be visible to a thread that has just made the count zero. // became zero will be visible to a thread that has just made the count zero.
inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) { inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
return base::AtomicRefCountDecN(ptr, 1); return base::AtomicRefCountDecN(ptr, 1);
} }
// Return whether the reference count is one. If the reference count is used // Return whether the reference count is one. If the reference count is used
// in the conventional way, a refrerence count of 1 implies that the current // in the conventional way, a refrerence count of 1 implies that the current
// thread owns the reference and no other thread shares it. This call performs // thread owns the reference and no other thread shares it. This call performs
// the test for a reference count of one, and performs the memory barrier // the test for a reference count of one, and performs the memory barrier
// needed for the owning thread to act on the object, knowing that it has // needed for the owning thread to act on the object, knowing that it has
// exclusive access to the object. // exclusive access to the object.
inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) { inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
return base::subtle::Acquire_Load(ptr) == 1; return base::subtle::Acquire_Load(ptr) == 1;
} }
// Return whether the reference count is zero. With conventional object // Return whether the reference count is zero. With conventional object
// referencing counting, the object will be destroyed, so the reference count // referencing counting, the object will be destroyed, so the reference count
// should never be zero. Hence this is generally used for a debug check. // should never be zero. Hence this is generally used for a debug check.
inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) { inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
return base::subtle::Acquire_Load(ptr) == 0; return base::subtle::Acquire_Load(ptr) == 0;
} }
} // namespace base } // namespace base
#endif // BASE_ATOMIC_REF_COUNT_H_ #endif // BASE_ATOMIC_REF_COUNT_H_

@@ -1,45 +1,45 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/base_paths_linux.h" #include "base/base_paths_linux.h"
#include <unistd.h> #include <unistd.h>
#include "base/file_util.h" #include "base/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/string_piece.h" #include "base/string_piece.h"
#include "base/sys_string_conversions.h" #include "base/sys_string_conversions.h"
namespace base { namespace base {
bool PathProviderLinux(int key, std::wstring* result) { bool PathProviderLinux(int key, std::wstring* result) {
std::wstring cur; std::wstring cur;
switch (key) { switch (key) {
case base::FILE_EXE: case base::FILE_EXE:
case base::FILE_MODULE: { // TODO(evanm): is this correct? case base::FILE_MODULE: { // TODO(evanm): is this correct?
char bin_dir[PATH_MAX + 1]; char bin_dir[PATH_MAX + 1];
int bin_dir_size = readlink("/proc/self/exe", bin_dir, PATH_MAX); int bin_dir_size = readlink("/proc/self/exe", bin_dir, PATH_MAX);
if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) { if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) {
NOTREACHED() << "Unable to resolve /proc/self/exe."; NOTREACHED() << "Unable to resolve /proc/self/exe.";
return false; return false;
} }
bin_dir[bin_dir_size] = 0; bin_dir[bin_dir_size] = 0;
*result = base::SysNativeMBToWide(bin_dir); *result = base::SysNativeMBToWide(bin_dir);
return true; return true;
} }
case base::DIR_SOURCE_ROOT: case base::DIR_SOURCE_ROOT:
// On linux, unit tests execute two levels deep from the source root. // On linux, unit tests execute two levels deep from the source root.
// For example: chrome/{Debug|Hammer}/net_unittest // For example: chrome/{Debug|Hammer}/net_unittest
PathService::Get(base::DIR_EXE, &cur); PathService::Get(base::DIR_EXE, &cur);
file_util::UpOneDirectory(&cur); file_util::UpOneDirectory(&cur);
file_util::UpOneDirectory(&cur); file_util::UpOneDirectory(&cur);
*result = cur; *result = cur;
return true; return true;
} }
return false; return false;
} }
} // namespace base } // namespace base

@@ -1,31 +1,31 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_BASE_PATHS_LINUX_H_ #ifndef BASE_BASE_PATHS_LINUX_H_
#define BASE_BASE_PATHS_LINUX_H_ #define BASE_BASE_PATHS_LINUX_H_
// This file declares Linux-specific path keys for the base module. // This file declares Linux-specific path keys for the base module.
// These can be used with the PathService to access various special // These can be used with the PathService to access various special
// directories and files. // directories and files.
namespace base { namespace base {
enum { enum {
PATH_LINUX_START = 200, PATH_LINUX_START = 200,
FILE_EXE, // Path and filename of the current executable. FILE_EXE, // Path and filename of the current executable.
FILE_MODULE, // Path and filename of the module containing the code for the FILE_MODULE, // Path and filename of the module containing the code for the
// PathService (which could differ from FILE_EXE if the // PathService (which could differ from FILE_EXE if the
// PathService were compiled into a shared object, for example). // PathService were compiled into a shared object, for example).
DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful
// for tests that need to locate various resources. It // for tests that need to locate various resources. It
// should not be used outside of test code. // should not be used outside of test code.
PATH_LINUX_END PATH_LINUX_END
}; };
} // namespace base } // namespace base
#endif // BASE_BASE_PATHS_LINUX_H_ #endif // BASE_BASE_PATHS_LINUX_H_

@@ -1,32 +1,32 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_BASE_PATHS_MAC_H_ #ifndef BASE_BASE_PATHS_MAC_H_
#define BASE_BASE_PATHS_MAC_H_ #define BASE_BASE_PATHS_MAC_H_
// This file declares Mac-specific path keys for the base module. // This file declares Mac-specific path keys for the base module.
// These can be used with the PathService to access various special // These can be used with the PathService to access various special
// directories and files. // directories and files.
namespace base { namespace base {
enum { enum {
PATH_MAC_START = 200, PATH_MAC_START = 200,
FILE_EXE, // path and filename of the current executable FILE_EXE, // path and filename of the current executable
FILE_MODULE, // path and filename of the module containing the code for the FILE_MODULE, // path and filename of the module containing the code for the
// PathService (which could differ from FILE_EXE if the // PathService (which could differ from FILE_EXE if the
// PathService were compiled into a library, for example) // PathService were compiled into a library, for example)
DIR_APP_DATA, // ~/Library/Application Support/Google/Chrome DIR_APP_DATA, // ~/Library/Application Support/Google/Chrome
DIR_LOCAL_APP_DATA, // same as above (can we remove?) DIR_LOCAL_APP_DATA, // same as above (can we remove?)
DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful
// for tests that need to locate various resources. It // for tests that need to locate various resources. It
// should not be used outside of test code. // should not be used outside of test code.
PATH_MAC_END PATH_MAC_END
}; };
} // namespace base } // namespace base
#endif // BASE_BASE_PATHS_MAC_H_ #endif // BASE_BASE_PATHS_MAC_H_

@@ -1,328 +1,328 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/file_util.h" #include "base/file_util.h"
#include <fcntl.h> #include <fcntl.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <fts.h> #include <fts.h>
#include <libgen.h> #include <libgen.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <fstream> #include <fstream>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/string_util.h" #include "base/string_util.h"
namespace file_util { namespace file_util {
std::wstring GetDirectoryFromPath(const std::wstring& path) { std::wstring GetDirectoryFromPath(const std::wstring& path) {
if (EndsWithSeparator(path)) { if (EndsWithSeparator(path)) {
std::wstring dir = path; std::wstring dir = path;
TrimTrailingSeparator(&dir); TrimTrailingSeparator(&dir);
return dir; return dir;
} else { } else {
char full_path[PATH_MAX]; char full_path[PATH_MAX];
base::strlcpy(full_path, WideToUTF8(path).c_str(), arraysize(full_path)); base::strlcpy(full_path, WideToUTF8(path).c_str(), arraysize(full_path));
return UTF8ToWide(dirname(full_path)); return UTF8ToWide(dirname(full_path));
} }
} }
bool AbsolutePath(std::wstring* path) { bool AbsolutePath(std::wstring* path) {
char full_path[PATH_MAX]; char full_path[PATH_MAX];
if (realpath(WideToUTF8(*path).c_str(), full_path) == NULL) if (realpath(WideToUTF8(*path).c_str(), full_path) == NULL)
return false; return false;
*path = UTF8ToWide(full_path); *path = UTF8ToWide(full_path);
return true; return true;
} }
// TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*" // TODO(erikkay): The Windows version of this accepts paths like "foo/bar/*"
// which works both with and without the recursive flag. I'm not sure we need // which works both with and without the recursive flag. I'm not sure we need
// that functionality. If not, remove from file_util_win.cc, otherwise add it // that functionality. If not, remove from file_util_win.cc, otherwise add it
// here. // here.
bool Delete(const std::wstring& path, bool recursive) { bool Delete(const std::wstring& path, bool recursive) {
const char* utf8_path = WideToUTF8(path).c_str(); const char* utf8_path = WideToUTF8(path).c_str();
struct stat64 file_info; struct stat64 file_info;
int test = stat64(utf8_path, &file_info); int test = stat64(utf8_path, &file_info);
if (test != 0) { if (test != 0) {
// The Windows version defines this condition as success. // The Windows version defines this condition as success.
bool ret = (errno == ENOENT || errno == ENOTDIR); bool ret = (errno == ENOENT || errno == ENOTDIR);
return ret; return ret;
} }
if (!S_ISDIR(file_info.st_mode)) if (!S_ISDIR(file_info.st_mode))
return (unlink(utf8_path) == 0); return (unlink(utf8_path) == 0);
if (!recursive) if (!recursive)
return (rmdir(utf8_path) == 0); return (rmdir(utf8_path) == 0);
bool success = true; bool success = true;
int ftsflags = FTS_PHYSICAL | FTS_NOSTAT; int ftsflags = FTS_PHYSICAL | FTS_NOSTAT;
char top_dir[PATH_MAX]; char top_dir[PATH_MAX];
base::strlcpy(top_dir, utf8_path, sizeof(top_dir)); base::strlcpy(top_dir, utf8_path, sizeof(top_dir));
char* dir_list[2] = { top_dir, NULL }; char* dir_list[2] = { top_dir, NULL };
FTS* fts = fts_open(dir_list, ftsflags, NULL); FTS* fts = fts_open(dir_list, ftsflags, NULL);
if (fts) { if (fts) {
FTSENT* fts_ent = fts_read(fts); FTSENT* fts_ent = fts_read(fts);
while (success && fts_ent != NULL) { while (success && fts_ent != NULL) {
switch (fts_ent->fts_info) { switch (fts_ent->fts_info) {
case FTS_DNR: case FTS_DNR:
case FTS_ERR: case FTS_ERR:
// log error // log error
success = false; success = false;
continue; continue;
break; break;
case FTS_DP: case FTS_DP:
rmdir(fts_ent->fts_accpath); rmdir(fts_ent->fts_accpath);
break; break;
case FTS_D: case FTS_D:
break; break;
case FTS_NSOK: case FTS_NSOK:
case FTS_F: case FTS_F:
case FTS_SL: case FTS_SL:
case FTS_SLNONE: case FTS_SLNONE:
unlink(fts_ent->fts_accpath); unlink(fts_ent->fts_accpath);
break; break;
default: default:
DCHECK(false); DCHECK(false);
break; break;
} }
fts_ent = fts_read(fts); fts_ent = fts_read(fts);
} }
fts_close(fts); fts_close(fts);
} }
return success; return success;
} }
bool Move(const std::wstring& from_path, const std::wstring& to_path) { bool Move(const std::wstring& from_path, const std::wstring& to_path) {
return (rename(WideToUTF8(from_path).c_str(), return (rename(WideToUTF8(from_path).c_str(),
WideToUTF8(to_path).c_str()) == 0); WideToUTF8(to_path).c_str()) == 0);
} }
bool CopyTree(const std::wstring& from_path, const std::wstring& to_path) { bool CopyTree(const std::wstring& from_path, const std::wstring& to_path) {
// TODO(erikkay): implement // TODO(erikkay): implement
return false; return false;
} }
bool PathExists(const std::wstring& path) { bool PathExists(const std::wstring& path) {
struct stat64 file_info; struct stat64 file_info;
return (stat64(WideToUTF8(path).c_str(), &file_info) == 0); return (stat64(WideToUTF8(path).c_str(), &file_info) == 0);
} }
// TODO(erikkay): implement // TODO(erikkay): implement
#if 0 #if 0
bool GetFileCreationLocalTimeFromHandle(int fd, bool GetFileCreationLocalTimeFromHandle(int fd,
LPSYSTEMTIME creation_time) { LPSYSTEMTIME creation_time) {
if (!file_handle) if (!file_handle)
return false; return false;
FILETIME utc_filetime; FILETIME utc_filetime;
if (!GetFileTime(file_handle, &utc_filetime, NULL, NULL)) if (!GetFileTime(file_handle, &utc_filetime, NULL, NULL))
return false; return false;
FILETIME local_filetime; FILETIME local_filetime;
if (!FileTimeToLocalFileTime(&utc_filetime, &local_filetime)) if (!FileTimeToLocalFileTime(&utc_filetime, &local_filetime))
return false; return false;
return !!FileTimeToSystemTime(&local_filetime, creation_time); return !!FileTimeToSystemTime(&local_filetime, creation_time);
} }
bool GetFileCreationLocalTime(const std::string& filename, bool GetFileCreationLocalTime(const std::string& filename,
LPSYSTEMTIME creation_time) { LPSYSTEMTIME creation_time) {
ScopedHandle file_handle( ScopedHandle file_handle(
CreateFile(filename.c_str(), GENERIC_READ, CreateFile(filename.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
return GetFileCreationLocalTimeFromHandle(file_handle.Get(), creation_time); return GetFileCreationLocalTimeFromHandle(file_handle.Get(), creation_time);
} }
#endif #endif
bool CreateTemporaryFileName(std::wstring* temp_file) { bool CreateTemporaryFileName(std::wstring* temp_file) {
std::wstring tmpdir; std::wstring tmpdir;
if (!GetTempDir(&tmpdir)) if (!GetTempDir(&tmpdir))
return false; return false;
tmpdir.append(L"com.google.chrome.XXXXXX"); tmpdir.append(L"com.google.chrome.XXXXXX");
// this should be OK since mktemp just replaces characters in place // this should be OK since mktemp just replaces characters in place
char* buffer = const_cast<char*>(WideToUTF8(tmpdir).c_str()); char* buffer = const_cast<char*>(WideToUTF8(tmpdir).c_str());
*temp_file = UTF8ToWide(mktemp(buffer)); *temp_file = UTF8ToWide(mktemp(buffer));
int fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); int fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) if (fd < 0)
return false; return false;
close(fd); close(fd);
return true; return true;
} }
bool CreateNewTempDirectory(const std::wstring& prefix, bool CreateNewTempDirectory(const std::wstring& prefix,
std::wstring* new_temp_path) { std::wstring* new_temp_path) {
std::wstring tmpdir; std::wstring tmpdir;
if (!GetTempDir(&tmpdir)) if (!GetTempDir(&tmpdir))
return false; return false;
tmpdir.append(L"/com.google.chrome.XXXXXX"); tmpdir.append(L"/com.google.chrome.XXXXXX");
// this should be OK since mkdtemp just replaces characters in place // this should be OK since mkdtemp just replaces characters in place
char* buffer = const_cast<char*>(WideToUTF8(tmpdir).c_str()); char* buffer = const_cast<char*>(WideToUTF8(tmpdir).c_str());
char* dtemp = mkdtemp(buffer); char* dtemp = mkdtemp(buffer);
if (!dtemp) if (!dtemp)
return false; return false;
*new_temp_path = UTF8ToWide(dtemp); *new_temp_path = UTF8ToWide(dtemp);
return true; return true;
} }
bool CreateDirectory(const std::wstring& full_path) { bool CreateDirectory(const std::wstring& full_path) {
std::vector<std::wstring> components; std::vector<std::wstring> components;
PathComponents(full_path, &components); PathComponents(full_path, &components);
std::wstring path; std::wstring path;
std::vector<std::wstring>::iterator i = components.begin(); std::vector<std::wstring>::iterator i = components.begin();
for (; i != components.end(); ++i) { for (; i != components.end(); ++i) {
if (path.length() == 0) if (path.length() == 0)
path = *i; path = *i;
else else
AppendToPath(&path, *i); AppendToPath(&path, *i);
if (!PathExists(path)) { if (!PathExists(path)) {
if (mkdir(WideToUTF8(path).c_str(), 0777) != 0) if (mkdir(WideToUTF8(path).c_str(), 0777) != 0)
return false; return false;
} }
} }
return true; return true;
} }
bool GetFileSize(const std::wstring& file_path, int64* file_size) { bool GetFileSize(const std::wstring& file_path, int64* file_size) {
struct stat64 file_info; struct stat64 file_info;
if (stat64(WideToUTF8(file_path).c_str(), &file_info) != 0) if (stat64(WideToUTF8(file_path).c_str(), &file_info) != 0)
return false; return false;
*file_size = file_info.st_size; *file_size = file_info.st_size;
return true; return true;
} }
int ReadFile(const std::wstring& filename, char* data, int size) { int ReadFile(const std::wstring& filename, char* data, int size) {
int fd = open(WideToUTF8(filename).c_str(), O_RDONLY); int fd = open(WideToUTF8(filename).c_str(), O_RDONLY);
if (fd < 0) if (fd < 0)
return -1; return -1;
int ret_value = read(fd, data, size); int ret_value = read(fd, data, size);
close(fd); close(fd);
return ret_value; return ret_value;
} }
int WriteFile(const std::wstring& filename, const char* data, int size) { int WriteFile(const std::wstring& filename, const char* data, int size) {
int fd = open(WideToUTF8(filename).c_str(), O_WRONLY | O_CREAT | O_TRUNC, int fd = open(WideToUTF8(filename).c_str(), O_WRONLY | O_CREAT | O_TRUNC,
0666); 0666);
if (fd < 0) if (fd < 0)
return -1; return -1;
int ret_value = write(fd, data, size); int ret_value = write(fd, data, size);
close(fd); close(fd);
return ret_value; return ret_value;
} }
// Gets the current working directory for the process. // Gets the current working directory for the process.
bool GetCurrentDirectory(std::wstring* dir) { bool GetCurrentDirectory(std::wstring* dir) {
char system_buffer[PATH_MAX] = ""; char system_buffer[PATH_MAX] = "";
getcwd(system_buffer, sizeof(system_buffer)); getcwd(system_buffer, sizeof(system_buffer));
*dir = UTF8ToWide(system_buffer); *dir = UTF8ToWide(system_buffer);
return true; return true;
} }
// Sets the current working directory for the process. // Sets the current working directory for the process.
bool SetCurrentDirectory(const std::wstring& current_directory) { bool SetCurrentDirectory(const std::wstring& current_directory) {
int ret = chdir(WideToUTF8(current_directory).c_str()); int ret = chdir(WideToUTF8(current_directory).c_str());
return (ret == 0); return (ret == 0);
} }
FileEnumerator::FileEnumerator(const std::wstring& root_path, FileEnumerator::FileEnumerator(const std::wstring& root_path,
bool recursive, bool recursive,
FileEnumerator::FILE_TYPE file_type) FileEnumerator::FILE_TYPE file_type)
: recursive_(recursive), : recursive_(recursive),
file_type_(file_type), file_type_(file_type),
is_in_find_op_(false), is_in_find_op_(false),
fts_(NULL) { fts_(NULL) {
pending_paths_.push(root_path); pending_paths_.push(root_path);
} }
FileEnumerator::FileEnumerator(const std::wstring& root_path, FileEnumerator::FileEnumerator(const std::wstring& root_path,
bool recursive, bool recursive,
FileEnumerator::FILE_TYPE file_type, FileEnumerator::FILE_TYPE file_type,
const std::wstring& pattern) const std::wstring& pattern)
: recursive_(recursive), : recursive_(recursive),
file_type_(file_type), file_type_(file_type),
pattern_(root_path), pattern_(root_path),
is_in_find_op_(false), is_in_find_op_(false),
fts_(NULL) { fts_(NULL) {
// The Windows version of this code only matches against items in the top-most // The Windows version of this code only matches against items in the top-most
// directory, and we're comparing fnmatch against full paths, so this is the // directory, and we're comparing fnmatch against full paths, so this is the
// easiest way to get the right pattern. // easiest way to get the right pattern.
AppendToPath(&pattern_, pattern); AppendToPath(&pattern_, pattern);
pending_paths_.push(root_path); pending_paths_.push(root_path);
} }
FileEnumerator::~FileEnumerator() { FileEnumerator::~FileEnumerator() {
if (fts_) if (fts_)
fts_close(fts_); fts_close(fts_);
} }
// As it stands, this method calls itself recursively when the next item of // As it stands, this method calls itself recursively when the next item of
// the fts enumeration doesn't match (type, pattern, etc.). In the case of // the fts enumeration doesn't match (type, pattern, etc.). In the case of
// large directories with many files this can be quite deep. // large directories with many files this can be quite deep.
// TODO(erikkay) - get rid of this recursive pattern // TODO(erikkay) - get rid of this recursive pattern
std::wstring FileEnumerator::Next() { std::wstring FileEnumerator::Next() {
if (!is_in_find_op_) { if (!is_in_find_op_) {
if (pending_paths_.empty()) if (pending_paths_.empty())
return std::wstring(); return std::wstring();
// The last find FindFirstFile operation is done, prepare a new one. // The last find FindFirstFile operation is done, prepare a new one.
root_path_ = pending_paths_.top(); root_path_ = pending_paths_.top();
TrimTrailingSeparator(&root_path_); TrimTrailingSeparator(&root_path_);
pending_paths_.pop(); pending_paths_.pop();
// Start a new find operation. // Start a new find operation.
int ftsflags = FTS_LOGICAL; int ftsflags = FTS_LOGICAL;
char top_dir[PATH_MAX]; char top_dir[PATH_MAX];
base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir)); base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir));
char* dir_list[2] = { top_dir, NULL }; char* dir_list[2] = { top_dir, NULL };
fts_ = fts_open(dir_list, ftsflags, NULL); fts_ = fts_open(dir_list, ftsflags, NULL);
if (!fts_) if (!fts_)
return Next(); return Next();
is_in_find_op_ = true; is_in_find_op_ = true;
} }
FTSENT* fts_ent = fts_read(fts_); FTSENT* fts_ent = fts_read(fts_);
if (fts_ent == NULL) { if (fts_ent == NULL) {
fts_close(fts_); fts_close(fts_);
fts_ = NULL; fts_ = NULL;
is_in_find_op_ = false; is_in_find_op_ = false;
return Next(); return Next();
} }
// Level 0 is the top, which is always skipped. // Level 0 is the top, which is always skipped.
if (fts_ent->fts_level == 0) if (fts_ent->fts_level == 0)
return Next(); return Next();
// Patterns are only matched on the items in the top-most directory. // Patterns are only matched on the items in the top-most directory.
// (see Windows implementation) // (see Windows implementation)
if (fts_ent->fts_level == 1 && pattern_.length() > 0) { if (fts_ent->fts_level == 1 && pattern_.length() > 0) {
const char* utf8_pattern = WideToUTF8(pattern_).c_str(); const char* utf8_pattern = WideToUTF8(pattern_).c_str();
if (fnmatch(utf8_pattern, fts_ent->fts_path, 0) != 0) { if (fnmatch(utf8_pattern, fts_ent->fts_path, 0) != 0) {
if (fts_ent->fts_info == FTS_D) if (fts_ent->fts_info == FTS_D)
fts_set(fts_, fts_ent, FTS_SKIP); fts_set(fts_, fts_ent, FTS_SKIP);
return Next(); return Next();
} }
} }
std::wstring cur_file(UTF8ToWide(fts_ent->fts_path)); std::wstring cur_file(UTF8ToWide(fts_ent->fts_path));
if (fts_ent->fts_info == FTS_D) { if (fts_ent->fts_info == FTS_D) {
// If not recursive, then prune children. // If not recursive, then prune children.
if (!recursive_) if (!recursive_)
fts_set(fts_, fts_ent, FTS_SKIP); fts_set(fts_, fts_ent, FTS_SKIP);
return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
} else if (fts_ent->fts_info == FTS_F) { } else if (fts_ent->fts_info == FTS_F) {
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
} }
// TODO(erikkay) - verify that the other fts_info types aren't interesting // TODO(erikkay) - verify that the other fts_info types aren't interesting
return Next(); return Next();
} }
} // namespace file_util } // namespace file_util

@@ -1,75 +1,75 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/message_pump_default.h" #include "base/message_pump_default.h"
#include "base/logging.h" #include "base/logging.h"
namespace base { namespace base {
MessagePumpDefault::MessagePumpDefault() MessagePumpDefault::MessagePumpDefault()
: keep_running_(true), : keep_running_(true),
event_(false, false) { event_(false, false) {
} }
void MessagePumpDefault::Run(Delegate* delegate) { void MessagePumpDefault::Run(Delegate* delegate) {
DCHECK(keep_running_) << "Quit must have been called outside of Run!"; DCHECK(keep_running_) << "Quit must have been called outside of Run!";
for (;;) { for (;;) {
bool did_work = delegate->DoWork(); bool did_work = delegate->DoWork();
if (!keep_running_) if (!keep_running_)
break; break;
did_work |= delegate->DoDelayedWork(&delayed_work_time_); did_work |= delegate->DoDelayedWork(&delayed_work_time_);
if (!keep_running_) if (!keep_running_)
break; break;
if (did_work) if (did_work)
continue; continue;
did_work = delegate->DoIdleWork(); did_work = delegate->DoIdleWork();
if (!keep_running_) if (!keep_running_)
break; break;
if (did_work) if (did_work)
continue; continue;
if (delayed_work_time_.is_null()) { if (delayed_work_time_.is_null()) {
event_.Wait(); event_.Wait();
} else { } else {
TimeDelta delay = delayed_work_time_ - Time::Now(); TimeDelta delay = delayed_work_time_ - Time::Now();
if (delay > TimeDelta()) { if (delay > TimeDelta()) {
event_.TimedWait(delay); event_.TimedWait(delay);
} else { } else {
// It looks like delayed_work_time_ indicates a time in the past, so we // It looks like delayed_work_time_ indicates a time in the past, so we
// need to call DoDelayedWork now. // need to call DoDelayedWork now.
delayed_work_time_ = Time(); delayed_work_time_ = Time();
} }
} }
// Since event_ is auto-reset, we don't need to do anything special here // Since event_ is auto-reset, we don't need to do anything special here
// other than service each delegate method. // other than service each delegate method.
} }
keep_running_ = true; keep_running_ = true;
} }
void MessagePumpDefault::Quit() { void MessagePumpDefault::Quit() {
keep_running_ = false; keep_running_ = false;
} }
void MessagePumpDefault::ScheduleWork() { void MessagePumpDefault::ScheduleWork() {
// Since this can be called on any thread, we need to ensure that our Run // Since this can be called on any thread, we need to ensure that our Run
// loop wakes up. // loop wakes up.
event_.Signal(); event_.Signal();
} }
void MessagePumpDefault::ScheduleDelayedWork(const Time& delayed_work_time) { void MessagePumpDefault::ScheduleDelayedWork(const Time& delayed_work_time) {
// We know that we can't be blocked on Wait right now since this method can // We know that we can't be blocked on Wait right now since this method can
// only be called on the same thread as Run, so we only need to update our // only be called on the same thread as Run, so we only need to update our
// record of how long to sleep when we do sleep. // record of how long to sleep when we do sleep.
delayed_work_time_ = delayed_work_time; delayed_work_time_ = delayed_work_time;
} }
} // namespace base } // namespace base

@@ -1,41 +1,41 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_MESSAGE_PUMP_DEFAULT_H_ #ifndef BASE_MESSAGE_PUMP_DEFAULT_H_
#define BASE_MESSAGE_PUMP_DEFAULT_H_ #define BASE_MESSAGE_PUMP_DEFAULT_H_
#include "base/message_pump.h" #include "base/message_pump.h"
#include "base/time.h" #include "base/time.h"
#include "base/waitable_event.h" #include "base/waitable_event.h"
namespace base { namespace base {
class MessagePumpDefault : public MessagePump { class MessagePumpDefault : public MessagePump {
public: public:
MessagePumpDefault(); MessagePumpDefault();
~MessagePumpDefault() {} ~MessagePumpDefault() {}
// MessagePump methods: // MessagePump methods:
virtual void Run(Delegate* delegate); virtual void Run(Delegate* delegate);
virtual void Quit(); virtual void Quit();
virtual void ScheduleWork(); virtual void ScheduleWork();
virtual void ScheduleDelayedWork(const Time& delayed_work_time); virtual void ScheduleDelayedWork(const Time& delayed_work_time);
private: private:
// This flag is set to false when Run should return. // This flag is set to false when Run should return.
bool keep_running_; bool keep_running_;
// Used to sleep until there is more work to do. // Used to sleep until there is more work to do.
WaitableEvent event_; WaitableEvent event_;
// The time at which we should call DoDelayedWork. // The time at which we should call DoDelayedWork.
Time delayed_work_time_; Time delayed_work_time_;
DISALLOW_COPY_AND_ASSIGN(MessagePumpDefault); DISALLOW_COPY_AND_ASSIGN(MessagePumpDefault);
}; };
} // namespace base } // namespace base
#endif // BASE_MESSAGE_PUMP_DEFAULT_H_ #endif // BASE_MESSAGE_PUMP_DEFAULT_H_

@@ -1,37 +1,37 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_PLATFORM_TEST_H_ #ifndef BASE_PLATFORM_TEST_H_
#define BASE_PLATFORM_TEST_H_ #define BASE_PLATFORM_TEST_H_
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#ifdef __OBJC__ #ifdef __OBJC__
@class NSAutoreleasePool; @class NSAutoreleasePool;
#else #else
class NSAutoreleasePool; class NSAutoreleasePool;
#endif #endif
// The purpose of this class us to provide a hook for platform-specific // The purpose of this class us to provide a hook for platform-specific
// SetUp and TearDown across unit tests. For example, on the Mac, it // SetUp and TearDown across unit tests. For example, on the Mac, it
// creates and releases an outer AutoreleasePool for each test. For now, it's // creates and releases an outer AutoreleasePool for each test. For now, it's
// only implemented on the Mac. To enable this for another platform, just // only implemented on the Mac. To enable this for another platform, just
// adjust the #ifdefs and add a platform_test_<platform>.cc implementation file. // adjust the #ifdefs and add a platform_test_<platform>.cc implementation file.
class PlatformTest : public testing::Test { class PlatformTest : public testing::Test {
protected: protected:
virtual void SetUp(); virtual void SetUp();
virtual void TearDown(); virtual void TearDown();
private: private:
NSAutoreleasePool* pool_; NSAutoreleasePool* pool_;
}; };
#else #else
typedef testing::Test PlatformTest; typedef testing::Test PlatformTest;
#endif // OS_MACOSX #endif // OS_MACOSX
#endif // BASE_PLATFORM_TEST_H_ #endif // BASE_PLATFORM_TEST_H_

@@ -1,36 +1,36 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/sys_string_conversions.h" #include "base/sys_string_conversions.h"
#include "base/string_piece.h" #include "base/string_piece.h"
#include "base/string_util.h" #include "base/string_util.h"
namespace base { namespace base {
std::string SysWideToUTF8(const std::wstring& wide) { std::string SysWideToUTF8(const std::wstring& wide) {
// In theory this should be using the system-provided conversion rather // In theory this should be using the system-provided conversion rather
// than our ICU, but this will do for now. // than our ICU, but this will do for now.
return WideToUTF8(wide); return WideToUTF8(wide);
} }
std::wstring SysUTF8ToWide(const StringPiece& utf8) { std::wstring SysUTF8ToWide(const StringPiece& utf8) {
// In theory this should be using the system-provided conversion rather // In theory this should be using the system-provided conversion rather
// than our ICU, but this will do for now. // than our ICU, but this will do for now.
std::wstring out; std::wstring out;
UTF8ToWide(utf8.data(), utf8.size(), &out); UTF8ToWide(utf8.data(), utf8.size(), &out);
return out; return out;
} }
std::string SysWideToNativeMB(const std::wstring& wide) { std::string SysWideToNativeMB(const std::wstring& wide) {
// TODO(evanm): we can't assume Linux is UTF-8. // TODO(evanm): we can't assume Linux is UTF-8.
return SysWideToUTF8(wide); return SysWideToUTF8(wide);
} }
std::wstring SysNativeMBToWide(const StringPiece& native_mb) { std::wstring SysNativeMBToWide(const StringPiece& native_mb) {
// TODO(evanm): we can't assume Linux is UTF-8. // TODO(evanm): we can't assume Linux is UTF-8.
return SysUTF8ToWide(native_mb); return SysUTF8ToWide(native_mb);
} }
} // namespace base } // namespace base

@@ -440,39 +440,63 @@ void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type) {
// that timers work properly in all configurations. // that timers work properly in all configurations.
TEST(TimerTest, TimerComparison) { TEST(TimerTest, TimerComparison) {
Time s = Time::Now();
RunTest_TimerComparison(MessageLoop::TYPE_DEFAULT); RunTest_TimerComparison(MessageLoop::TYPE_DEFAULT);
RunTest_TimerComparison(MessageLoop::TYPE_UI); RunTest_TimerComparison(MessageLoop::TYPE_UI);
RunTest_TimerComparison(MessageLoop::TYPE_IO); RunTest_TimerComparison(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("comparison elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, BasicTimer) { TEST(TimerTest, BasicTimer) {
Time s = Time::Now();
RunTest_BasicTimer(MessageLoop::TYPE_DEFAULT); RunTest_BasicTimer(MessageLoop::TYPE_DEFAULT);
RunTest_BasicTimer(MessageLoop::TYPE_UI); RunTest_BasicTimer(MessageLoop::TYPE_UI);
RunTest_BasicTimer(MessageLoop::TYPE_IO); RunTest_BasicTimer(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("basic elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, BrokenTimer) { TEST(TimerTest, BrokenTimer) {
Time s = Time::Now();
RunTest_BrokenTimer(MessageLoop::TYPE_DEFAULT); RunTest_BrokenTimer(MessageLoop::TYPE_DEFAULT);
RunTest_BrokenTimer(MessageLoop::TYPE_UI); RunTest_BrokenTimer(MessageLoop::TYPE_UI);
RunTest_BrokenTimer(MessageLoop::TYPE_IO); RunTest_BrokenTimer(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("broken elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, DeleteFromRun) { TEST(TimerTest, DeleteFromRun) {
Time s = Time::Now();
RunTest_DeleteFromRun(MessageLoop::TYPE_DEFAULT); RunTest_DeleteFromRun(MessageLoop::TYPE_DEFAULT);
RunTest_DeleteFromRun(MessageLoop::TYPE_UI); RunTest_DeleteFromRun(MessageLoop::TYPE_UI);
RunTest_DeleteFromRun(MessageLoop::TYPE_IO); RunTest_DeleteFromRun(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("delete elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, Reset) { TEST(TimerTest, Reset) {
Time s = Time::Now();
RunTest_Reset(MessageLoop::TYPE_DEFAULT); RunTest_Reset(MessageLoop::TYPE_DEFAULT);
RunTest_Reset(MessageLoop::TYPE_UI); RunTest_Reset(MessageLoop::TYPE_UI);
RunTest_Reset(MessageLoop::TYPE_IO); RunTest_Reset(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("reset elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, FifoOrder) { TEST(TimerTest, FifoOrder) {
Time s = Time::Now();
RunTest_FifoOrder(MessageLoop::TYPE_DEFAULT); RunTest_FifoOrder(MessageLoop::TYPE_DEFAULT);
RunTest_FifoOrder(MessageLoop::TYPE_UI); RunTest_FifoOrder(MessageLoop::TYPE_UI);
RunTest_FifoOrder(MessageLoop::TYPE_IO); RunTest_FifoOrder(MessageLoop::TYPE_IO);
Time e = Time::Now();
TimeDelta el = e - s;
printf("fifo elapsed time %lld\n", el.ToInternalValue());
} }
TEST(TimerTest, OneShotTimer) { TEST(TimerTest, OneShotTimer) {

@@ -1,83 +1,83 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef BASE_WAITABLE_EVENT_H_ #ifndef BASE_WAITABLE_EVENT_H_
#define BASE_WAITABLE_EVENT_H_ #define BASE_WAITABLE_EVENT_H_
#include "base/basictypes.h" #include "base/basictypes.h"
#if defined(OS_WIN) #if defined(OS_WIN)
typedef void* HANDLE; typedef void* HANDLE;
#else #else
#include "base/condition_variable.h" #include "base/condition_variable.h"
#include "base/lock.h" #include "base/lock.h"
#endif #endif
class TimeDelta; class TimeDelta;
namespace base { namespace base {
// A WaitableEvent can be a useful thread synchronization tool when you want to // A WaitableEvent can be a useful thread synchronization tool when you want to
// allow one thread to wait for another thread to finish some work. // allow one thread to wait for another thread to finish some work.
// //
// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to // Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to
// protect a simple boolean value. However, if you find yourself using a // protect a simple boolean value. However, if you find yourself using a
// WaitableEvent in conjunction with a Lock to wait for a more complex state // WaitableEvent in conjunction with a Lock to wait for a more complex state
// change (e.g., for an item to be added to a queue), then you should probably // change (e.g., for an item to be added to a queue), then you should probably
// be using a ConditionVariable instead of a WaitableEvent. // be using a ConditionVariable instead of a WaitableEvent.
// //
// NOTE: On Windows, this class provides a subset of the functionality afforded // NOTE: On Windows, this class provides a subset of the functionality afforded
// by a Windows event object. This is intentional. If you are writing Windows // by a Windows event object. This is intentional. If you are writing Windows
// specific code and you need other features of a Windows event, then you might // specific code and you need other features of a Windows event, then you might
// be better off just using an Windows event directly. // be better off just using an Windows event directly.
// //
class WaitableEvent { class WaitableEvent {
public: public:
// If manual_reset is true, then to set the event state to non-signaled, a // If manual_reset is true, then to set the event state to non-signaled, a
// consumer must call the Reset method. If this parameter is false, then the // consumer must call the Reset method. If this parameter is false, then the
// system automatically resets the event state to non-signaled after a single // system automatically resets the event state to non-signaled after a single
// waiting thread has been released. // waiting thread has been released.
WaitableEvent(bool manual_reset, bool initially_signaled); WaitableEvent(bool manual_reset, bool initially_signaled);
// WARNING: Destroying a WaitableEvent while threads are waiting on it is not // WARNING: Destroying a WaitableEvent while threads are waiting on it is not
// supported. Doing so will cause crashes or other instability. // supported. Doing so will cause crashes or other instability.
~WaitableEvent(); ~WaitableEvent();
// Put the event in the un-signaled state. // Put the event in the un-signaled state.
void Reset(); void Reset();
// Put the event in the signaled state. Causing any thread blocked on Wait // Put the event in the signaled state. Causing any thread blocked on Wait
// to be woken up. // to be woken up.
void Signal(); void Signal();
// Returns true if the event is in the signaled state, else false. If this // Returns true if the event is in the signaled state, else false. If this
// is not a manual reset event, then this test will cause a reset. // is not a manual reset event, then this test will cause a reset.
bool IsSignaled(); bool IsSignaled();
// Wait indefinitely for the event to be signaled. Returns true if the event // Wait indefinitely for the event to be signaled. Returns true if the event
// was signaled, else false is returned to indicate that waiting failed. // was signaled, else false is returned to indicate that waiting failed.
bool Wait(); bool Wait();
// Wait up until max_time has passed for the event to be signaled. Returns // Wait up until max_time has passed for the event to be signaled. Returns
// true if the event was signaled. If this method returns false, then it // true if the event was signaled. If this method returns false, then it
// does not necessarily mean that max_time was exceeded. // does not necessarily mean that max_time was exceeded.
bool TimedWait(const TimeDelta& max_time); bool TimedWait(const TimeDelta& max_time);
private: private:
#if defined(OS_WIN) #if defined(OS_WIN)
HANDLE event_; HANDLE event_;
#else #else
Lock lock_; // Needs to be listed first so it will be constructed first. Lock lock_; // Needs to be listed first so it will be constructed first.
ConditionVariable cvar_; ConditionVariable cvar_;
bool signaled_; bool signaled_;
bool manual_reset_; bool manual_reset_;
#endif #endif
DISALLOW_COPY_AND_ASSIGN(WaitableEvent); DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
}; };
} // namespace base } // namespace base
#endif // BASE_WAITABLE_EVENT_H_ #endif // BASE_WAITABLE_EVENT_H_

@@ -1,66 +1,66 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/waitable_event.h" #include "base/waitable_event.h"
#include <math.h> #include <math.h>
#include <windows.h> #include <windows.h>
#include "base/logging.h" #include "base/logging.h"
#include "base/time.h" #include "base/time.h"
namespace base { namespace base {
WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) WaitableEvent::WaitableEvent(bool manual_reset, bool signaled)
: event_(CreateEvent(NULL, manual_reset, signaled, NULL)) { : event_(CreateEvent(NULL, manual_reset, signaled, NULL)) {
// We're probably going to crash anyways if this is ever NULL, so we might as // We're probably going to crash anyways if this is ever NULL, so we might as
// well make our stack reports more informative by crashing here. // well make our stack reports more informative by crashing here.
CHECK(event_); CHECK(event_);
} }
WaitableEvent::~WaitableEvent() { WaitableEvent::~WaitableEvent() {
CloseHandle(event_); CloseHandle(event_);
} }
void WaitableEvent::Reset() { void WaitableEvent::Reset() {
ResetEvent(event_); ResetEvent(event_);
} }
void WaitableEvent::Signal() { void WaitableEvent::Signal() {
SetEvent(event_); SetEvent(event_);
} }
bool WaitableEvent::IsSignaled() { bool WaitableEvent::IsSignaled() {
return TimedWait(TimeDelta::FromMilliseconds(0)); return TimedWait(TimeDelta::FromMilliseconds(0));
} }
bool WaitableEvent::Wait() { bool WaitableEvent::Wait() {
DWORD result = WaitForSingleObject(event_, INFINITE); DWORD result = WaitForSingleObject(event_, INFINITE);
// It is most unexpected that this should ever fail. Help consumers learn // It is most unexpected that this should ever fail. Help consumers learn
// about it if it should ever fail. // about it if it should ever fail.
DCHECK(result == WAIT_OBJECT_0) << "WaitForSingleObject failed"; DCHECK(result == WAIT_OBJECT_0) << "WaitForSingleObject failed";
return result == WAIT_OBJECT_0; return result == WAIT_OBJECT_0;
} }
bool WaitableEvent::TimedWait(const TimeDelta& max_time) { bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); DCHECK(max_time >= TimeDelta::FromMicroseconds(0));
// Be careful here. TimeDelta has a precision of microseconds, but this API // 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? // 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. // It should be 6 to avoid returning too early.
double timeout = ceil(max_time.InMillisecondsF()); double timeout = ceil(max_time.InMillisecondsF());
DWORD result = WaitForSingleObject(event_, static_cast<DWORD>(timeout)); DWORD result = WaitForSingleObject(event_, static_cast<DWORD>(timeout));
switch (result) { switch (result) {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
return true; return true;
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
return false; return false;
} }
// It is most unexpected that this should ever fail. Help consumers learn // It is most unexpected that this should ever fail. Help consumers learn
// about it if it should ever fail. // about it if it should ever fail.
NOTREACHED() << "WaitForSingleObject failed"; NOTREACHED() << "WaitForSingleObject failed";
return false; return false;
} }
} // namespace base } // namespace base