0

Add base to the repository.

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
initial.commit
2008-07-26 21:49:38 +00:00
parent ee2815e28d
commit d7cae12696
371 changed files with 60061 additions and 0 deletions
base
SConscriptSConstructatomic.hatomic_unittest.ccbase.sln
base.xcodeproj
base_drag_source.ccbase_drag_source.hbase_drop_target.ccbase_drop_target.hbase_paths.ccbase_paths.hbase_switches.ccbase_switches.hbasictypes.h
build
check_handler.hcheck_handler_unittest.ccclipboard.ccclipboard.hclipboard_unittest.ccclipboard_util.ccclipboard_util.hcommand_line.cccommand_line.hcommand_line_unittest.cccondition_variable.cccondition_variable.hcondition_variable_test.cc
data
file_util_unittest
file_version_info_unittest
purify
vectorcanvastest
basicdrawing
bitmaps
circles
clippingclean
clippingcombined
clippingintersect
clippingpath
clippingrect
diagonallines
lineorientation
matrix
patheffects
pathorientation
uninitialized
debug_message.ccdebug_on_start.ccdebug_on_start.hdebug_util.ccdebug_util.hevent_recorder.ccevent_recorder.hfile_util.ccfile_util.hfile_util_unittest.ccfile_version_info.ccfile_version_info.hfile_version_info_unittest.ccfix_wp64.hfixed_string.hfixed_string_unittest.cc
gfx
hash_tables.hhistogram.cchistogram.hhistogram_test.cchmac.cchmac.hhmac_unittest.cciat_patch.cciat_patch.hicu_util.ccicu_util.hid_map.hidle_timer.ccidle_timer.hidletimer_unittest.ccimage_util.ccimage_util.hjson_reader.ccjson_reader.hjson_reader_unittest.ccjson_writer.ccjson_writer.hjson_writer_unittest.cclinked_ptr.hlinked_ptr_unittest.cclock.cclock.hlock_impl.hlock_impl_mac.cclock_impl_win.cclogging.cclogging.hmd5.ccmd5.hmemory_debug.ccmemory_debug.hmessage_loop.ccmessage_loop.hmessage_loop_unittest.ccmultiprocess_test.hno_windows2000_unittest.hnon_thread_safe.ccnon_thread_safe.hobserver_list.hobserver_list_unittest.ccpath_service.ccpath_service.hpath_service_unittest.ccpe_image.ccpe_image.hpe_image_unittest.ccperftimer.ccperftimer.hpickle.ccpickle.hpickle_unittest.ccplatform_thread.ccplatform_thread.hport.hpr_time_test.ccprocess.ccprocess.hprocess_util.ccprocess_util.hprocess_util_unittest.ccref_counted.href_counted_unittest.ccregistry.ccregistry.hresource_util.ccresource_util.hrevocable_store.ccrevocable_store.hrun_all_perftests.ccrun_all_unittests.ccscoped_cftyperef.hscoped_handle.hscoped_ptr.hsha2.ccsha2.hsha2_unittest.ccshared_event.ccshared_event.hshared_event_unittest.ccshared_memory.ccshared_memory.hshared_memory_unittest.ccsingleton.hsingleton_dll_unittest.ccsingleton_dll_unittest.hsingleton_internal.hsingleton_unittest.ccspin_wait.hstack_container.hstack_container_unittest.ccstats_counters.hstats_table.ccstats_table.hstats_table_unittest.ccstring16.hstring_escape.ccstring_escape.hstring_escape_unittest.ccstring_piece.ccstring_piece.hstring_piece_unittest.ccstring_tokenizer.hstring_tokenizer_unittest.ccstring_util.ccstring_util.hstring_util_icu.ccstring_util_mac.ccstring_util_mac.hstring_util_unittest.ccstring_util_win.ccstring_util_win.htask.htest_suite.h
third_party
thread.ccthread.hthread_local_storage.hthread_local_storage_unittest.ccthread_local_storage_win.ccthread_unittest.cctime.cctime.htime_mac.cctime_unittest.cctime_win.cctimer.cctimer.htimer_unittest.cctracked.cctracked.htracked_objects.cctracked_objects.htracked_objects_test.cctuple.hvalues.ccvalues.hvalues_unittest.ccwatchdog.ccwatchdog.hwatchdog_test.ccwin_util.ccwin_util.hwin_util_unittest.ccwindows_message_list.hwmi_util.ccwmi_util.hwmi_util_unittest.ccword_iterator.ccword_iterator.hworker_pool.ccworker_pool.h

296
base/SConscript Normal file

@ -0,0 +1,296 @@
# Copyright 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Import('env')
env = env.Clone()
env_tests = env.Clone()
env.Prepend(
CPPPATH = [
'$ICU38_DIR/public/common',
'$ICU38_DIR/public/i18n',
'..',
],
CPPDEFINES = [
'U_STATIC_IMPLEMENTATION',
'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
'WIN32_LEAN_AND_MEAN',
],
CCFLAGS = [
'/TP',
'/Wp64',
'/wd4503',
'/wd4819',
],
)
input_files = [
'base_drag_source.cc',
'base_drop_target.cc',
'base_paths.cc',
'base_switches.cc',
'clipboard.cc',
'clipboard_util.cc',
'command_line.cc',
'condition_variable.cc',
'debug_on_start.cc',
'debug_util.cc',
'event_recorder.cc',
'file_util.cc',
'file_version_info.cc',
'histogram.cc',
'hmac.cc',
'iat_patch.cc',
'icu_util.cc',
'idle_timer.cc',
'image_util.cc',
'json_reader.cc',
'json_writer.cc',
'lock.cc',
'lock_impl_win.cc',
'logging.cc',
'md5.cc',
'memory_debug.cc',
'message_loop.cc',
'non_thread_safe.cc',
'path_service.cc',
'pe_image.cc',
'pickle.cc',
'platform_thread.cc',
'process.cc',
'process_util.cc',
'registry.cc',
'resource_util.cc',
'revocable_store.cc',
'sha2.cc',
'shared_event.cc',
'shared_memory.cc',
'stats_table.cc',
'string_escape.cc',
'string_util.cc',
'string_util_icu.cc',
'string_util_win.cc',
'third_party/nspr/prtime.cc',
'third_party/nss/sha512.cc',
'thread.cc',
'thread_local_storage_win.cc',
'time.cc',
'time_win.cc',
'timer.cc',
'tracked.cc',
'tracked_objects.cc',
'values.cc',
'watchdog.cc',
'win_util.cc',
'wmi_util.cc',
'word_iterator.cc',
'worker_pool.cc',
]
env.StaticLibrary('base', input_files)
env_tests.Prepend(
CPPPATH = [
'$SKIA_DIR/include',
'$SKIA_DIR/include/corecg',
'$SKIA_DIR/platform',
'$ZLIB_DIR',
'$LIBPNG_DIR',
'$ICU38_DIR/public/common',
'$ICU38/_DIRpublic/i18n',
'..',
],
CPPDEFINES = [
'UNIT_TEST',
'PNG_USER_CONFIG',
'CHROME_PNG_WRITE_SUPPORT',
'U_STATIC_IMPLEMENTATION',
'_WIN32_WINNT=0x0600',
'WINVER=0x0600',
'_HAS_EXCEPTIONS=0',
'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
'WIN32_LEAN_AND_MEAN',
],
CCFLAGS = [
'/WX',
'/Wp64',
'/TP',
'/wd4503',
'/wd4819',
],
LINKFLAGS = [
'/MANIFEST',
'/DELAYLOAD:"dwmapi.dll"',
'/DELAYLOAD:"uxtheme.dll"',
'/MACHINE:X86',
'/FIXED:No',
'/safeseh',
'/dynamicbase',
'/ignore:4199',
'/nxcompat',
],
LIBS = [
'advapi32.lib',
'comdlg32.lib',
'DelayImp.lib',
'gdi32.lib',
'kernel32.lib',
'msimg32.lib',
'odbc32.lib',
'odbccp32.lib',
'ole32.lib',
'oleaut32.lib',
'psapi.lib',
'shell32.lib',
'user32.lib',
'usp10.lib',
'uuid.lib',
'version.lib',
'wininet.lib',
'winspool.lib',
'ws2_32.lib',
],
)
libs = [
'base.lib',
'gfx/base_gfx.lib',
'$SKIA_DIR/skia.lib',
'$LIBPNG_DIR/libpng.lib',
'$TESTING_DIR/gtest.lib',
'$ICU38_DIR/icuuc.lib',
'$ZLIB_DIR/zlib.lib',
]
env_tests.Append(
CPPPATH = [
'$GTEST_DIR/include',
],
)
env_tests_dll = env_tests.Clone()
env_tests_dll.Append(
CPPDEFINES = [
'_WINDLL',
'SINGLETON_UNITTEST_EXPORTS',
],
)
dll = env_tests_dll.SharedLibrary(['singleton_dll_unittest.dll',
'singleton_dll_unittest.ilk',
'singleton_dll_unittest.pdb'],
['singleton_dll_unittest.cc',
'build/singleton_dll_unittest.def'] + libs)
i = env.Install('$TARGET_ROOT', dll[0])
env.Alias('base', i)
env_tests.Program(['debug_message.exe',
'debug_message.ilk',
'debug_message.pdb'],
['debug_message.cc'] + libs)
test_files = [
'atomic_unittest.cc',
'check_handler_unittest.cc',
'clipboard_unittest.cc',
'command_line_unittest.cc',
'condition_variable_test.cc',
'file_util_unittest.cc',
'file_version_info_unittest.cc',
'fixed_string_unittest.cc',
'gfx/convolver_unittest.cc',
'gfx/image_operations_unittest.cc',
'gfx/native_theme_unittest.cc',
'gfx/platform_canvas_unittest.cc',
'gfx/png_codec_unittest.cc',
'gfx/rect_unittest.cc',
'gfx/uniscribe_unittest.cc',
'gfx/vector_canvas_unittest.cc',
'hmac_unittest.cc',
'json_reader_unittest.cc',
'json_writer_unittest.cc',
'linked_ptr_unittest.cc',
'message_loop_unittest.cc',
'path_service_unittest.cc',
'pe_image_unittest.cc',
'pickle_unittest.cc',
'pr_time_test.cc',
'process_util_unittest.cc',
'ref_counted_unittest.cc',
'run_all_unittests.cc',
'sha2_unittest.cc',
'shared_event_unittest.cc',
'shared_memory_unittest.cc',
'singleton_unittest.cc',
'stack_container_unittest.cc',
'stats_table_unittest.cc',
'string_tokenizer_unittest.cc',
'string_util_unittest.cc',
'thread_local_storage_unittest.cc',
'thread_unittest.cc',
'tracked_objects_test.cc',
'time_unittest.cc',
'timer_unittest.cc',
'values_unittest.cc',
'win_util_unittest.cc',
'wmi_util_unittest.cc',
'singleton_dll_unittest.lib',
]
base_unittests = env_tests.Program([
'base_unittests',
'base_unittests.exp',
'base_unittests.ilk',
'base_unittests.lib',
'base_unittests.pdb'], test_files + libs)
# Install up a level to allow unit test path assumptions to be valid.
installed_base_unittests = env.Install('$TARGET_ROOT', base_unittests)
sconscript_dirs = [
'gfx/SConscript',
]
SConscript(sconscript_dirs, exports=['env'])
# Setup alias for all base related targets.
env.Alias('base', ['.', installed_base_unittests, '../icudt38.dll'])
env_tests.StaticObject('perftimer.cc')
env_tests.StaticObject('run_all_perftests.cc')

3
base/SConstruct Normal file

@ -0,0 +1,3 @@
build_component = 'base'
SConscript('../build/SConscript.main',
exports=['build_component'])

111
base/atomic.h Normal file

@ -0,0 +1,111 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_ATOMIC_H__
#define BASE_ATOMIC_H__
#if defined(WIN32)
#include <windows.h>
#elif defined(__APPLE__)
#include <libkern/OSAtomic.h>
#else
#error Implement atomic support on your platform
#endif
#include "base/basictypes.h"
namespace base {
///////////////////////////////////////////////////////////////////////////
//
// Forward declarations and descriptions of the functions
//
///////////////////////////////////////////////////////////////////////////
// Atomically increments *value and returns the resulting incremented value.
// This function implies no memory barriers.
int32 AtomicIncrement(volatile int32* value);
// Atomically decrements *value and returns the resulting decremented value.
// This function implies no memory barriers.
int32 AtomicDecrement(volatile int32* value);
// Atomically sets *target to new_value and returns the old value of *target.
// This function implies no memory barriers.
int32 AtomicSwap(volatile int32* target, int32 new_value);
///////////////////////////////////////////////////////////////////////////
//
// Implementations for various platforms
//
///////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
inline int32 AtomicIncrement(volatile int32* value) {
return InterlockedIncrement(reinterpret_cast<volatile LONG*>(value));
}
inline int32 AtomicDecrement(volatile int32* value) {
return InterlockedDecrement(reinterpret_cast<volatile LONG*>(value));
}
inline int32 AtomicSwap(volatile int32* target, int32 new_value) {
return InterlockedExchange(reinterpret_cast<volatile LONG*>(target),
new_value);
}
#elif defined(__APPLE__)
inline int32 AtomicIncrement(volatile int32* value) {
return OSAtomicIncrement32(reinterpret_cast<volatile int32_t*>(value));
}
inline int32 AtomicDecrement(volatile int32* value) {
return OSAtomicDecrement32(reinterpret_cast<volatile int32_t*>(value));
}
inline int32 AtomicSwap(volatile int32* target, int32 new_value) {
int32 old_value;
do {
old_value = *target;
} while (!OSAtomicCompareAndSwap32(old_value, new_value,
reinterpret_cast<volatile int32_t*>(target)));
return old_value;
}
#else
#error Implement atomic support on your platform
#endif
} // namespace base
#endif // BASE_ATOMIC_H__

63
base/atomic_unittest.cc Normal file

@ -0,0 +1,63 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/atomic.h"
#include "base/lock.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(AtomicTest, Increment) {
int32 value = 38;
int32 new_value = base::AtomicIncrement(&value);
EXPECT_EQ(39, value);
EXPECT_EQ(39, new_value);
}
TEST(AtomicTest, Decrement) {
int32 value = 49;
int32 new_value = base::AtomicDecrement(&value);
EXPECT_EQ(48, value);
EXPECT_EQ(48, new_value);
}
TEST(AtomicTest, Swap) {
int32 value = 38;
int32 old_value = base::AtomicSwap(&value, 49);
EXPECT_EQ(49, value);
EXPECT_EQ(38, old_value);
// Now do another test.
value = 0;
old_value = base::AtomicSwap(&value, 1);
EXPECT_EQ(0, old_value);
old_value = base::AtomicSwap(&value, 1);
EXPECT_EQ(1, old_value);
old_value = base::AtomicSwap(&value, 1);
EXPECT_EQ(1, old_value);
}

109
base/base.sln Normal file

@ -0,0 +1,109 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "build\base.vcproj", "{1832A374-8A74-4F9E-B536-69A699B3E165}"
ProjectSection(ProjectDependencies) = postProject
{0E5474AC-5996-4B13-87C0-4AE931EE0815} = {0E5474AC-5996-4B13-87C0-4AE931EE0815}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base_unittests", "build\base_unittests.vcproj", "{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}"
ProjectSection(ProjectDependencies) = postProject
{1832A374-8A74-4F9E-B536-69A699B3E165} = {1832A374-8A74-4F9E-B536-69A699B3E165}
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C} = {8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}
{8C27D792-2648-4F5E-9ED0-374276327308} = {8C27D792-2648-4F5E-9ED0-374276327308}
{A508ADD3-CECE-4E0F-8448-2F5E454DF551} = {A508ADD3-CECE-4E0F-8448-2F5E454DF551}
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B} = {BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}
{C564F145-9172-42C3-BFCB-6014CA97DBCD} = {C564F145-9172-42C3-BFCB-6014CA97DBCD}
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D} = {CD9CA56E-4E94-444C-87D4-58CA1E6F300D}
{E457F2FB-4708-4001-9B1C-275D7BD7F2A8} = {E457F2FB-4708-4001-9B1C-275D7BD7F2A8}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "debug_message", "build\debug_message.vcproj", "{0E5474AC-5996-4B13-87C0-4AE931EE0815}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{F216062D-F9C4-4883-A52C-2BE9ECADEEA0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icuuc", "..\third_party\icu38\build\icuuc.vcproj", "{8C27D792-2648-4F5E-9ED0-374276327308}"
ProjectSection(ProjectDependencies) = postProject
{A0D94973-D355-47A5-A1E2-3456F321F010} = {A0D94973-D355-47A5-A1E2-3456F321F010}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icudt", "..\third_party\icu38\build\icudt.vcproj", "{A0D94973-D355-47A5-A1E2-3456F321F010}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base_gfx", "build\base_gfx.vcproj", "{A508ADD3-CECE-4E0F-8448-2F5E454DF551}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "skia", "..\skia\skia.vcproj", "{CD9CA56E-4E94-444C-87D4-58CA1E6F300D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "..\third_party\libpng\libpng.vcproj", "{C564F145-9172-42C3-BFCB-6014CA97DBCD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\third_party\zlib\zlib.vcproj", "{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "singleton_dll_unittest", "build\singleton_unittest.vcproj", "{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}"
ProjectSection(ProjectDependencies) = postProject
{1832A374-8A74-4F9E-B536-69A699B3E165} = {1832A374-8A74-4F9E-B536-69A699B3E165}
{8C27D792-2648-4F5E-9ED0-374276327308} = {8C27D792-2648-4F5E-9ED0-374276327308}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\testing\gtest.vcproj", "{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0E5474AC-5996-4B13-87C0-4AE931EE0815}.Debug|Win32.ActiveCfg = Debug|Win32
{0E5474AC-5996-4B13-87C0-4AE931EE0815}.Debug|Win32.Build.0 = Debug|Win32
{0E5474AC-5996-4B13-87C0-4AE931EE0815}.Release|Win32.ActiveCfg = Release|Win32
{0E5474AC-5996-4B13-87C0-4AE931EE0815}.Release|Win32.Build.0 = Release|Win32
{1832A374-8A74-4F9E-B536-69A699B3E165}.Debug|Win32.ActiveCfg = Debug|Win32
{1832A374-8A74-4F9E-B536-69A699B3E165}.Debug|Win32.Build.0 = Debug|Win32
{1832A374-8A74-4F9E-B536-69A699B3E165}.Release|Win32.ActiveCfg = Release|Win32
{1832A374-8A74-4F9E-B536-69A699B3E165}.Release|Win32.Build.0 = Release|Win32
{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}.Debug|Win32.ActiveCfg = Debug|Win32
{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}.Debug|Win32.Build.0 = Debug|Win32
{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}.Release|Win32.ActiveCfg = Release|Win32
{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}.Release|Win32.Build.0 = Release|Win32
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}.Debug|Win32.ActiveCfg = Debug|Win32
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}.Debug|Win32.Build.0 = Debug|Win32
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}.Release|Win32.ActiveCfg = Release|Win32
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}.Release|Win32.Build.0 = Release|Win32
{8C27D792-2648-4F5E-9ED0-374276327308}.Debug|Win32.ActiveCfg = Debug|Win32
{8C27D792-2648-4F5E-9ED0-374276327308}.Debug|Win32.Build.0 = Debug|Win32
{8C27D792-2648-4F5E-9ED0-374276327308}.Release|Win32.ActiveCfg = Release|Win32
{8C27D792-2648-4F5E-9ED0-374276327308}.Release|Win32.Build.0 = Release|Win32
{A0D94973-D355-47A5-A1E2-3456F321F010}.Debug|Win32.ActiveCfg = Debug|Win32
{A0D94973-D355-47A5-A1E2-3456F321F010}.Debug|Win32.Build.0 = Debug|Win32
{A0D94973-D355-47A5-A1E2-3456F321F010}.Release|Win32.ActiveCfg = Release|Win32
{A0D94973-D355-47A5-A1E2-3456F321F010}.Release|Win32.Build.0 = Release|Win32
{A508ADD3-CECE-4E0F-8448-2F5E454DF551}.Debug|Win32.ActiveCfg = Debug|Win32
{A508ADD3-CECE-4E0F-8448-2F5E454DF551}.Debug|Win32.Build.0 = Debug|Win32
{A508ADD3-CECE-4E0F-8448-2F5E454DF551}.Release|Win32.ActiveCfg = Release|Win32
{A508ADD3-CECE-4E0F-8448-2F5E454DF551}.Release|Win32.Build.0 = Release|Win32
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}.Debug|Win32.ActiveCfg = Debug|Win32
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}.Debug|Win32.Build.0 = Debug|Win32
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}.Release|Win32.ActiveCfg = Release|Win32
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}.Release|Win32.Build.0 = Release|Win32
{C564F145-9172-42C3-BFCB-6014CA97DBCD}.Debug|Win32.ActiveCfg = Debug|Win32
{C564F145-9172-42C3-BFCB-6014CA97DBCD}.Debug|Win32.Build.0 = Debug|Win32
{C564F145-9172-42C3-BFCB-6014CA97DBCD}.Release|Win32.ActiveCfg = Release|Win32
{C564F145-9172-42C3-BFCB-6014CA97DBCD}.Release|Win32.Build.0 = Release|Win32
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D}.Debug|Win32.ActiveCfg = Debug|Win32
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D}.Debug|Win32.Build.0 = Debug|Win32
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D}.Release|Win32.ActiveCfg = Release|Win32
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D}.Release|Win32.Build.0 = Release|Win32
{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}.Debug|Win32.ActiveCfg = Debug|Win32
{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}.Debug|Win32.Build.0 = Debug|Win32
{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}.Release|Win32.ActiveCfg = Release|Win32
{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
{8C27D792-2648-4F5E-9ED0-374276327308} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
{A0D94973-D355-47A5-A1E2-3456F321F010} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
{C564F145-9172-42C3-BFCB-6014CA97DBCD} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
{CD9CA56E-4E94-444C-87D4-58CA1E6F300D} = {F216062D-F9C4-4883-A52C-2BE9ECADEEA0}
EndGlobalSection
EndGlobal

@ -0,0 +1,970 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXAggregateTarget section */
825404020D92D3340006B936 /* All */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 825404110D92D35C0006B936 /* Build configuration list for PBXAggregateTarget "All" */;
buildPhases = (
);
dependencies = (
825404060D92D33A0006B936 /* PBXTargetDependency */,
825404080D92D33C0006B936 /* PBXTargetDependency */,
);
name = All;
productName = All;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
7B5AD60E0D9DD8050012BCF1 /* scoped_cftyperef.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5AD60D0D9DD8050012BCF1 /* scoped_cftyperef.h */; };
7BD9E84F0DA447F800FC7A01 /* singleton.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD9E84E0DA447F800FC7A01 /* singleton.h */; };
7BEB81110D9AD288009BA8DD /* prcpucfg_mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BEB81100D9AD288009BA8DD /* prcpucfg_mac.h */; };
7BEB814A0D9B0F33009BA8DD /* time_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BEB81490D9B0F33009BA8DD /* time_mac.cc */; };
7BEB834E0D9C4BE0009BA8DD /* string_util_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BEB834D0D9C4BE0009BA8DD /* string_util_mac.cc */; };
7BEE52C20D9D84FD0067FF23 /* string_util_mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BEE52C10D9D84FD0067FF23 /* string_util_mac.h */; };
7BEFC29E0D99832D000829AD /* lock_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BEFC29C0D99832D000829AD /* lock_impl.h */; };
7BEFC29F0D99832D000829AD /* lock_impl_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BEFC29D0D99832D000829AD /* lock_impl_mac.cc */; };
821B91690DAABD7F00F350D7 /* string16.h in Headers */ = {isa = PBXBuildFile; fileRef = 821B91680DAABD7F00F350D7 /* string16.h */; };
825402CE0D92D1390006B936 /* base_drag_source.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402C50D92D1390006B936 /* base_drag_source.cc */; };
825402CF0D92D1390006B936 /* base_drag_source.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402C60D92D1390006B936 /* base_drag_source.h */; };
825402D00D92D1390006B936 /* base_drop_target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402C70D92D1390006B936 /* base_drop_target.cc */; };
825402D10D92D1390006B936 /* base_drop_target.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402C80D92D1390006B936 /* base_drop_target.h */; };
825402D20D92D1390006B936 /* base_paths.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402C90D92D1390006B936 /* base_paths.cc */; };
825402D30D92D1390006B936 /* base_paths.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402CA0D92D1390006B936 /* base_paths.h */; };
825402D40D92D1390006B936 /* base_switches.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402CB0D92D1390006B936 /* base_switches.cc */; };
825402D50D92D1390006B936 /* base_switches.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402CC0D92D1390006B936 /* base_switches.h */; };
825402D60D92D1390006B936 /* basictypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402CD0D92D1390006B936 /* basictypes.h */; };
825402D90D92D15E0006B936 /* blapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402D70D92D15E0006B936 /* blapi.h */; };
825402DA0D92D15E0006B936 /* blapit.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402D80D92D15E0006B936 /* blapit.h */; };
825402DF0D92D1730006B936 /* clipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402DB0D92D1730006B936 /* clipboard.h */; };
825402E00D92D1730006B936 /* clipboard.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402DC0D92D1730006B936 /* clipboard.cc */; };
825402E10D92D1730006B936 /* clipboard_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402DD0D92D1730006B936 /* clipboard_util.h */; };
825402E20D92D1730006B936 /* clipboard_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402DE0D92D1730006B936 /* clipboard_util.cc */; };
825402E50D92D1850006B936 /* command_line.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402E30D92D1850006B936 /* command_line.cc */; };
825402E60D92D1850006B936 /* command_line.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402E40D92D1850006B936 /* command_line.h */; };
825402EE0D92D1940006B936 /* condition_variable.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402EB0D92D1940006B936 /* condition_variable.h */; };
825402EF0D92D1940006B936 /* condition_variable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402EC0D92D1940006B936 /* condition_variable.cc */; };
825402F00D92D1940006B936 /* condition_variable_events.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402ED0D92D1940006B936 /* condition_variable_events.h */; };
825402F50D92D1AC0006B936 /* debug_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402F10D92D1AC0006B936 /* debug_util.h */; };
825402F60D92D1AC0006B936 /* debug_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402F20D92D1AC0006B936 /* debug_util.cc */; };
825402F70D92D1AC0006B936 /* debug_on_start.h in Headers */ = {isa = PBXBuildFile; fileRef = 825402F30D92D1AC0006B936 /* debug_on_start.h */; };
825402F80D92D1AC0006B936 /* debug_on_start.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402F40D92D1AC0006B936 /* debug_on_start.cc */; };
825403010D92D1BC0006B936 /* event_recorder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825402FF0D92D1BC0006B936 /* event_recorder.cc */; };
825403020D92D1BC0006B936 /* event_recorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403000D92D1BC0006B936 /* event_recorder.h */; };
825403050D92D1C50006B936 /* file_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403030D92D1C50006B936 /* file_util.h */; };
825403060D92D1C50006B936 /* file_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403040D92D1C50006B936 /* file_util.cc */; };
825403090D92D1CD0006B936 /* file_version_info.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403070D92D1CD0006B936 /* file_version_info.h */; };
8254030A0D92D1CD0006B936 /* file_version_info.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403080D92D1CD0006B936 /* file_version_info.cc */; };
8254030C0D92D1D10006B936 /* fix_wp64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254030B0D92D1D10006B936 /* fix_wp64.h */; };
8254030E0D92D1DB0006B936 /* fixed_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254030D0D92D1DB0006B936 /* fixed_string.h */; };
825403140D92D1E80006B936 /* iat_patch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254030F0D92D1E80006B936 /* iat_patch.cc */; };
825403150D92D1E80006B936 /* iat_patch.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403100D92D1E80006B936 /* iat_patch.h */; };
825403160D92D1E80006B936 /* icu_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403110D92D1E80006B936 /* icu_util.cc */; };
825403170D92D1E80006B936 /* icu_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403120D92D1E80006B936 /* icu_util.h */; };
825403180D92D1E80006B936 /* id_map.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403130D92D1E80006B936 /* id_map.h */; };
8254031F0D92D1F40006B936 /* image_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403190D92D1F40006B936 /* image_util.cc */; };
825403200D92D1F40006B936 /* image_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254031A0D92D1F40006B936 /* image_util.h */; };
825403210D92D1F40006B936 /* json_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254031B0D92D1F40006B936 /* json_reader.cc */; };
825403220D92D1F40006B936 /* json_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254031C0D92D1F40006B936 /* json_reader.h */; };
825403230D92D1F40006B936 /* json_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254031D0D92D1F40006B936 /* json_writer.cc */; };
825403240D92D1F40006B936 /* json_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254031E0D92D1F40006B936 /* json_writer.h */; };
8254032D0D92D2090006B936 /* lock.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403250D92D2090006B936 /* lock.cc */; };
8254032E0D92D2090006B936 /* lock.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403260D92D2090006B936 /* lock.h */; };
8254032F0D92D2090006B936 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403270D92D2090006B936 /* logging.cc */; };
825403300D92D2090006B936 /* logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403280D92D2090006B936 /* logging.h */; };
825403310D92D2090006B936 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403290D92D2090006B936 /* md5.cc */; };
825403320D92D2090006B936 /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254032A0D92D2090006B936 /* md5.h */; };
825403330D92D2090006B936 /* memory_debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254032B0D92D2090006B936 /* memory_debug.cc */; };
825403340D92D2090006B936 /* memory_debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254032C0D92D2090006B936 /* memory_debug.h */; };
825403370D92D2110006B936 /* message_loop.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403350D92D2110006B936 /* message_loop.cc */; };
825403380D92D2110006B936 /* message_loop.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403360D92D2110006B936 /* message_loop.h */; };
825403410D92D2210006B936 /* observer_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403390D92D2210006B936 /* observer_list.h */; };
825403420D92D2210006B936 /* path_service.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254033A0D92D2210006B936 /* path_service.cc */; };
825403430D92D2210006B936 /* path_service.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254033B0D92D2210006B936 /* path_service.h */; };
825403440D92D2210006B936 /* pe_image.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254033C0D92D2210006B936 /* pe_image.cc */; };
825403450D92D2210006B936 /* pe_image.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254033D0D92D2210006B936 /* pe_image.h */; };
825403460D92D2210006B936 /* pickle.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254033E0D92D2210006B936 /* pickle.cc */; };
825403470D92D2210006B936 /* pickle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254033F0D92D2210006B936 /* pickle.h */; };
825403480D92D2210006B936 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403400D92D2210006B936 /* port.h */; };
8254034D0D92D23C0006B936 /* prtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403490D92D23C0006B936 /* prtypes.h */; };
8254034E0D92D23C0006B936 /* prtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254034A0D92D23C0006B936 /* prtime.h */; };
8254034F0D92D23C0006B936 /* prtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254034B0D92D23C0006B936 /* prtime.cc */; };
825403500D92D23C0006B936 /* prcpucfg.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254034C0D92D23C0006B936 /* prcpucfg.h */; };
825403530D92D24D0006B936 /* process_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403510D92D24D0006B936 /* process_util.h */; };
825403540D92D24D0006B936 /* process_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403520D92D24D0006B936 /* process_util.cc */; };
825403560D92D2580006B936 /* pure.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403550D92D2580006B936 /* pure.h */; };
825403580D92D25E0006B936 /* pure_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 825403570D92D25E0006B936 /* pure_api.c */; };
825403640D92D27C0006B936 /* ref_counted.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403590D92D27C0006B936 /* ref_counted.h */; };
825403650D92D27C0006B936 /* registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254035A0D92D27C0006B936 /* registry.cc */; };
825403660D92D27C0006B936 /* registry.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254035B0D92D27C0006B936 /* registry.h */; };
825403670D92D27C0006B936 /* resource_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254035C0D92D27C0006B936 /* resource_util.cc */; };
825403680D92D27C0006B936 /* resource_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254035D0D92D27C0006B936 /* resource_util.h */; };
825403690D92D27C0006B936 /* revocable_store.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254035E0D92D27C0006B936 /* revocable_store.cc */; };
8254036A0D92D27C0006B936 /* revocable_store.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254035F0D92D27C0006B936 /* revocable_store.h */; };
8254036C0D92D27C0006B936 /* scoped_ptr.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403610D92D27C0006B936 /* scoped_ptr.h */; };
8254036D0D92D27C0006B936 /* sha2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403620D92D27C0006B936 /* sha2.cc */; };
8254036E0D92D27C0006B936 /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403630D92D27C0006B936 /* sha2.h */; };
825403710D92D2840006B936 /* sha256.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254036F0D92D2840006B936 /* sha256.h */; };
825403720D92D2840006B936 /* sha512.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403700D92D2840006B936 /* sha512.cc */; };
825403900D92D2CF0006B936 /* shared_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403730D92D2CF0006B936 /* shared_event.cc */; };
825403910D92D2CF0006B936 /* shared_event.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403740D92D2CF0006B936 /* shared_event.h */; };
825403920D92D2CF0006B936 /* shared_memory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403750D92D2CF0006B936 /* shared_memory.cc */; };
825403930D92D2CF0006B936 /* shared_memory.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403760D92D2CF0006B936 /* shared_memory.h */; };
825403940D92D2CF0006B936 /* stack_container.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403770D92D2CF0006B936 /* stack_container.h */; };
825403950D92D2CF0006B936 /* stats_counters.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403780D92D2CF0006B936 /* stats_counters.h */; };
825403960D92D2CF0006B936 /* stats_table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403790D92D2CF0006B936 /* stats_table.cc */; };
825403970D92D2CF0006B936 /* stats_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254037A0D92D2CF0006B936 /* stats_table.h */; };
825403980D92D2CF0006B936 /* string_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254037B0D92D2CF0006B936 /* string_tokenizer.h */; };
825403990D92D2CF0006B936 /* string_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254037C0D92D2CF0006B936 /* string_util.cc */; };
8254039A0D92D2CF0006B936 /* string_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254037D0D92D2CF0006B936 /* string_util.h */; };
8254039B0D92D2CF0006B936 /* task.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254037E0D92D2CF0006B936 /* task.h */; };
8254039C0D92D2CF0006B936 /* thread.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254037F0D92D2CF0006B936 /* thread.cc */; };
8254039D0D92D2CF0006B936 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403800D92D2CF0006B936 /* thread.h */; };
8254039E0D92D2CF0006B936 /* thread_local_storage.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403810D92D2CF0006B936 /* thread_local_storage.cc */; };
8254039F0D92D2CF0006B936 /* thread_local_storage.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403820D92D2CF0006B936 /* thread_local_storage.h */; };
825403A00D92D2CF0006B936 /* time.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403830D92D2CF0006B936 /* time.cc */; };
825403A10D92D2CF0006B936 /* time.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403840D92D2CF0006B936 /* time.h */; };
825403A20D92D2CF0006B936 /* timer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403850D92D2CF0006B936 /* timer.cc */; };
825403A30D92D2CF0006B936 /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403860D92D2CF0006B936 /* timer.h */; };
825403A40D92D2CF0006B936 /* tuple.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403870D92D2CF0006B936 /* tuple.h */; };
825403A50D92D2CF0006B936 /* values.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403880D92D2CF0006B936 /* values.cc */; };
825403A60D92D2CF0006B936 /* values.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403890D92D2CF0006B936 /* values.h */; };
825403A70D92D2CF0006B936 /* win_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254038A0D92D2CF0006B936 /* win_util.cc */; };
825403A80D92D2CF0006B936 /* win_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254038B0D92D2CF0006B936 /* win_util.h */; };
825403A90D92D2CF0006B936 /* wmi_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254038C0D92D2CF0006B936 /* wmi_util.cc */; };
825403AA0D92D2CF0006B936 /* wmi_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254038D0D92D2CF0006B936 /* wmi_util.h */; };
825403AB0D92D2CF0006B936 /* word_iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8254038E0D92D2CF0006B936 /* word_iterator.cc */; };
825403AC0D92D2CF0006B936 /* word_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8254038F0D92D2CF0006B936 /* word_iterator.h */; };
825403E10D92D31D0006B936 /* bitmap_header.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403C00D92D31D0006B936 /* bitmap_header.cc */; };
825403E20D92D31D0006B936 /* bitmap_header.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403C10D92D31D0006B936 /* bitmap_header.h */; };
825403E30D92D31D0006B936 /* bitmap_platform_device.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403C20D92D31D0006B936 /* bitmap_platform_device.cc */; };
825403E40D92D31D0006B936 /* bitmap_platform_device.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403C30D92D31D0006B936 /* bitmap_platform_device.h */; };
825403E50D92D31D0006B936 /* font_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403C40D92D31D0006B936 /* font_utils.cc */; };
825403E60D92D31D0006B936 /* font_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403C50D92D31D0006B936 /* font_utils.h */; };
825403E70D92D31D0006B936 /* image_resizer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403C60D92D31D0006B936 /* image_resizer.cc */; };
825403E80D92D31D0006B936 /* image_resizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403C70D92D31D0006B936 /* image_resizer.h */; };
825403E90D92D31D0006B936 /* native_theme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403C80D92D31D0006B936 /* native_theme.cc */; };
825403EA0D92D31D0006B936 /* native_theme.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403C90D92D31D0006B936 /* native_theme.h */; };
825403EB0D92D31D0006B936 /* platform_canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403CA0D92D31D0006B936 /* platform_canvas.h */; };
825403EC0D92D31D0006B936 /* platform_device.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403CB0D92D31D0006B936 /* platform_device.cc */; };
825403ED0D92D31D0006B936 /* platform_device.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403CC0D92D31D0006B936 /* platform_device.h */; };
825403EE0D92D31D0006B936 /* png_decoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403CD0D92D31D0006B936 /* png_decoder.cc */; };
825403EF0D92D31D0006B936 /* png_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403CE0D92D31D0006B936 /* png_decoder.h */; };
825403F00D92D31D0006B936 /* png_encoder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403CF0D92D31D0006B936 /* png_encoder.cc */; };
825403F10D92D31D0006B936 /* png_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403D00D92D31D0006B936 /* png_encoder.h */; };
825403F20D92D31D0006B936 /* point.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403D10D92D31D0006B936 /* point.cc */; };
825403F30D92D31D0006B936 /* point.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403D20D92D31D0006B936 /* point.h */; };
825403F40D92D31D0006B936 /* rect_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403D30D92D31D0006B936 /* rect_unittest.cc */; };
825403F50D92D31D0006B936 /* rect.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403D40D92D31D0006B936 /* rect.cc */; };
825403F60D92D31D0006B936 /* rect.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403D50D92D31D0006B936 /* rect.h */; };
825403F70D92D31D0006B936 /* size.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403D60D92D31D0006B936 /* size.cc */; };
825403F80D92D31D0006B936 /* size.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403D70D92D31D0006B936 /* size.h */; };
825403F90D92D31D0006B936 /* skia_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403D80D92D31D0006B936 /* skia_utils.cc */; };
825403FA0D92D31D0006B936 /* skia_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403D90D92D31D0006B936 /* skia_utils.h */; };
825403FB0D92D31D0006B936 /* uniscribe.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403DA0D92D31D0006B936 /* uniscribe.cc */; };
825403FC0D92D31D0006B936 /* uniscribe.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403DB0D92D31D0006B936 /* uniscribe.h */; };
825403FD0D92D31D0006B936 /* vector_canvas.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403DC0D92D31D0006B936 /* vector_canvas.cc */; };
825403FE0D92D31D0006B936 /* vector_canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403DD0D92D31D0006B936 /* vector_canvas.h */; };
825403FF0D92D31D0006B936 /* vector_device.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403DE0D92D31D0006B936 /* vector_device.cc */; };
825404000D92D31D0006B936 /* vector_device.h in Headers */ = {isa = PBXBuildFile; fileRef = 825403DF0D92D31D0006B936 /* vector_device.h */; };
825404010D92D31D0006B936 /* platform_canvas.cc in Sources */ = {isa = PBXBuildFile; fileRef = 825403E00D92D31D0006B936 /* platform_canvas.cc */; };
82E23FCD0D9C219600F8B40A /* platform_thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 82E23FCB0D9C219600F8B40A /* platform_thread.h */; };
82E23FCE0D9C219600F8B40A /* platform_thread.cc in Sources */ = {isa = PBXBuildFile; fileRef = 82E23FCC0D9C219600F8B40A /* platform_thread.cc */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
825404050D92D33A0006B936 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 825402AA0D92D0C60006B936 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 825402BA0D92D0FA0006B936;
remoteInfo = base;
};
825404070D92D33C0006B936 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 825402AA0D92D0C60006B936 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 825403B00D92D2E50006B936;
remoteInfo = base_gfx;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
7B5AD60D0D9DD8050012BCF1 /* scoped_cftyperef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scoped_cftyperef.h; sourceTree = "<group>"; };
7BD9E84E0DA447F800FC7A01 /* singleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = singleton.h; sourceTree = "<group>"; };
7BEB81100D9AD288009BA8DD /* prcpucfg_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prcpucfg_mac.h; path = third_party/nspr/prcpucfg_mac.h; sourceTree = "<group>"; };
7BEB81490D9B0F33009BA8DD /* time_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = time_mac.cc; sourceTree = "<group>"; };
7BEB834D0D9C4BE0009BA8DD /* string_util_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_util_mac.cc; sourceTree = "<group>"; };
7BEE52C10D9D84FD0067FF23 /* string_util_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_util_mac.h; sourceTree = "<group>"; };
7BEFC29C0D99832D000829AD /* lock_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lock_impl.h; sourceTree = "<group>"; };
7BEFC29D0D99832D000829AD /* lock_impl_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lock_impl_mac.cc; sourceTree = "<group>"; };
821B91680DAABD7F00F350D7 /* string16.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string16.h; sourceTree = "<group>"; };
825402BB0D92D0FA0006B936 /* libbase.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libbase.a; sourceTree = BUILT_PRODUCTS_DIR; };
825402C50D92D1390006B936 /* base_drag_source.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_drag_source.cc; sourceTree = "<group>"; };
825402C60D92D1390006B936 /* base_drag_source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_drag_source.h; sourceTree = "<group>"; };
825402C70D92D1390006B936 /* base_drop_target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_drop_target.cc; sourceTree = "<group>"; };
825402C80D92D1390006B936 /* base_drop_target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_drop_target.h; sourceTree = "<group>"; };
825402C90D92D1390006B936 /* base_paths.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_paths.cc; sourceTree = "<group>"; };
825402CA0D92D1390006B936 /* base_paths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_paths.h; sourceTree = "<group>"; };
825402CB0D92D1390006B936 /* base_switches.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_switches.cc; sourceTree = "<group>"; };
825402CC0D92D1390006B936 /* base_switches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_switches.h; sourceTree = "<group>"; };
825402CD0D92D1390006B936 /* basictypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = basictypes.h; sourceTree = "<group>"; };
825402D70D92D15E0006B936 /* blapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = blapi.h; path = third_party/nss/blapi.h; sourceTree = "<group>"; };
825402D80D92D15E0006B936 /* blapit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = blapit.h; path = third_party/nss/blapit.h; sourceTree = "<group>"; };
825402DB0D92D1730006B936 /* clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clipboard.h; sourceTree = "<group>"; };
825402DC0D92D1730006B936 /* clipboard.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard.cc; sourceTree = "<group>"; };
825402DD0D92D1730006B936 /* clipboard_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clipboard_util.h; sourceTree = "<group>"; };
825402DE0D92D1730006B936 /* clipboard_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard_util.cc; sourceTree = "<group>"; };
825402E30D92D1850006B936 /* command_line.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = command_line.cc; sourceTree = "<group>"; };
825402E40D92D1850006B936 /* command_line.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = command_line.h; sourceTree = "<group>"; };
825402EB0D92D1940006B936 /* condition_variable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = condition_variable.h; sourceTree = "<group>"; };
825402EC0D92D1940006B936 /* condition_variable.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = condition_variable.cc; sourceTree = "<group>"; };
825402ED0D92D1940006B936 /* condition_variable_events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = condition_variable_events.h; sourceTree = "<group>"; };
825402F10D92D1AC0006B936 /* debug_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_util.h; sourceTree = "<group>"; };
825402F20D92D1AC0006B936 /* debug_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_util.cc; sourceTree = "<group>"; };
825402F30D92D1AC0006B936 /* debug_on_start.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_on_start.h; sourceTree = "<group>"; };
825402F40D92D1AC0006B936 /* debug_on_start.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_on_start.cc; sourceTree = "<group>"; };
825402FF0D92D1BC0006B936 /* event_recorder.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event_recorder.cc; sourceTree = "<group>"; };
825403000D92D1BC0006B936 /* event_recorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event_recorder.h; sourceTree = "<group>"; };
825403030D92D1C50006B936 /* file_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_util.h; sourceTree = "<group>"; };
825403040D92D1C50006B936 /* file_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_util.cc; sourceTree = "<group>"; };
825403070D92D1CD0006B936 /* file_version_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_version_info.h; sourceTree = "<group>"; };
825403080D92D1CD0006B936 /* file_version_info.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_version_info.cc; sourceTree = "<group>"; };
8254030B0D92D1D10006B936 /* fix_wp64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fix_wp64.h; sourceTree = "<group>"; };
8254030D0D92D1DB0006B936 /* fixed_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixed_string.h; sourceTree = "<group>"; };
8254030F0D92D1E80006B936 /* iat_patch.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iat_patch.cc; sourceTree = "<group>"; };
825403100D92D1E80006B936 /* iat_patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iat_patch.h; sourceTree = "<group>"; };
825403110D92D1E80006B936 /* icu_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = icu_util.cc; sourceTree = "<group>"; };
825403120D92D1E80006B936 /* icu_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icu_util.h; sourceTree = "<group>"; };
825403130D92D1E80006B936 /* id_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = id_map.h; sourceTree = "<group>"; };
825403190D92D1F40006B936 /* image_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image_util.cc; sourceTree = "<group>"; };
8254031A0D92D1F40006B936 /* image_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image_util.h; sourceTree = "<group>"; };
8254031B0D92D1F40006B936 /* json_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_reader.cc; sourceTree = "<group>"; };
8254031C0D92D1F40006B936 /* json_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_reader.h; sourceTree = "<group>"; };
8254031D0D92D1F40006B936 /* json_writer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_writer.cc; sourceTree = "<group>"; };
8254031E0D92D1F40006B936 /* json_writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_writer.h; sourceTree = "<group>"; };
825403250D92D2090006B936 /* lock.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lock.cc; sourceTree = "<group>"; };
825403260D92D2090006B936 /* lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lock.h; sourceTree = "<group>"; };
825403270D92D2090006B936 /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logging.cc; sourceTree = "<group>"; };
825403280D92D2090006B936 /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = "<group>"; };
825403290D92D2090006B936 /* md5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = md5.cc; sourceTree = "<group>"; };
8254032A0D92D2090006B936 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
8254032B0D92D2090006B936 /* memory_debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_debug.cc; sourceTree = "<group>"; };
8254032C0D92D2090006B936 /* memory_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_debug.h; sourceTree = "<group>"; };
825403350D92D2110006B936 /* message_loop.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_loop.cc; sourceTree = "<group>"; };
825403360D92D2110006B936 /* message_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_loop.h; sourceTree = "<group>"; };
825403390D92D2210006B936 /* observer_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = observer_list.h; sourceTree = "<group>"; };
8254033A0D92D2210006B936 /* path_service.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path_service.cc; sourceTree = "<group>"; };
8254033B0D92D2210006B936 /* path_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path_service.h; sourceTree = "<group>"; };
8254033C0D92D2210006B936 /* pe_image.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pe_image.cc; sourceTree = "<group>"; };
8254033D0D92D2210006B936 /* pe_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pe_image.h; sourceTree = "<group>"; };
8254033E0D92D2210006B936 /* pickle.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pickle.cc; sourceTree = "<group>"; };
8254033F0D92D2210006B936 /* pickle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pickle.h; sourceTree = "<group>"; };
825403400D92D2210006B936 /* port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = port.h; sourceTree = "<group>"; };
825403490D92D23C0006B936 /* prtypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prtypes.h; path = third_party/nspr/prtypes.h; sourceTree = "<group>"; };
8254034A0D92D23C0006B936 /* prtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prtime.h; path = third_party/nspr/prtime.h; sourceTree = "<group>"; };
8254034B0D92D23C0006B936 /* prtime.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = prtime.cc; path = third_party/nspr/prtime.cc; sourceTree = "<group>"; };
8254034C0D92D23C0006B936 /* prcpucfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prcpucfg.h; path = third_party/nspr/prcpucfg.h; sourceTree = "<group>"; };
825403510D92D24D0006B936 /* process_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process_util.h; sourceTree = "<group>"; };
825403520D92D24D0006B936 /* process_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = process_util.cc; sourceTree = "<group>"; };
825403550D92D2580006B936 /* pure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pure.h; path = third_party/purify/pure.h; sourceTree = "<group>"; };
825403570D92D25E0006B936 /* pure_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pure_api.c; path = third_party/purify/pure_api.c; sourceTree = "<group>"; };
825403590D92D27C0006B936 /* ref_counted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ref_counted.h; sourceTree = "<group>"; };
8254035A0D92D27C0006B936 /* registry.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = registry.cc; sourceTree = "<group>"; };
8254035B0D92D27C0006B936 /* registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registry.h; sourceTree = "<group>"; };
8254035C0D92D27C0006B936 /* resource_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource_util.cc; sourceTree = "<group>"; };
8254035D0D92D27C0006B936 /* resource_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource_util.h; sourceTree = "<group>"; };
8254035E0D92D27C0006B936 /* revocable_store.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = revocable_store.cc; sourceTree = "<group>"; };
8254035F0D92D27C0006B936 /* revocable_store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = revocable_store.h; sourceTree = "<group>"; };
825403610D92D27C0006B936 /* scoped_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scoped_ptr.h; sourceTree = "<group>"; };
825403620D92D27C0006B936 /* sha2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sha2.cc; sourceTree = "<group>"; };
825403630D92D27C0006B936 /* sha2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha2.h; sourceTree = "<group>"; };
8254036F0D92D2840006B936 /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha256.h; path = third_party/nss/sha256.h; sourceTree = "<group>"; };
825403700D92D2840006B936 /* sha512.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sha512.cc; path = third_party/nss/sha512.cc; sourceTree = "<group>"; };
825403730D92D2CF0006B936 /* shared_event.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_event.cc; sourceTree = "<group>"; };
825403740D92D2CF0006B936 /* shared_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_event.h; sourceTree = "<group>"; };
825403750D92D2CF0006B936 /* shared_memory.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory.cc; sourceTree = "<group>"; };
825403760D92D2CF0006B936 /* shared_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_memory.h; sourceTree = "<group>"; };
825403770D92D2CF0006B936 /* stack_container.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_container.h; sourceTree = "<group>"; };
825403780D92D2CF0006B936 /* stats_counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stats_counters.h; sourceTree = "<group>"; };
825403790D92D2CF0006B936 /* stats_table.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stats_table.cc; sourceTree = "<group>"; };
8254037A0D92D2CF0006B936 /* stats_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stats_table.h; sourceTree = "<group>"; };
8254037B0D92D2CF0006B936 /* string_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_tokenizer.h; sourceTree = "<group>"; };
8254037C0D92D2CF0006B936 /* string_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_util.cc; sourceTree = "<group>"; };
8254037D0D92D2CF0006B936 /* string_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_util.h; sourceTree = "<group>"; };
8254037E0D92D2CF0006B936 /* task.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = task.h; sourceTree = "<group>"; };
8254037F0D92D2CF0006B936 /* thread.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread.cc; sourceTree = "<group>"; };
825403800D92D2CF0006B936 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread.h; sourceTree = "<group>"; };
825403810D92D2CF0006B936 /* thread_local_storage.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_storage.cc; sourceTree = "<group>"; };
825403820D92D2CF0006B936 /* thread_local_storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread_local_storage.h; sourceTree = "<group>"; };
825403830D92D2CF0006B936 /* time.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = time.cc; sourceTree = "<group>"; };
825403840D92D2CF0006B936 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = "<group>"; };
825403850D92D2CF0006B936 /* timer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer.cc; sourceTree = "<group>"; };
825403860D92D2CF0006B936 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = "<group>"; };
825403870D92D2CF0006B936 /* tuple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tuple.h; sourceTree = "<group>"; };
825403880D92D2CF0006B936 /* values.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = values.cc; sourceTree = "<group>"; };
825403890D92D2CF0006B936 /* values.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = values.h; sourceTree = "<group>"; };
8254038A0D92D2CF0006B936 /* win_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = win_util.cc; sourceTree = "<group>"; };
8254038B0D92D2CF0006B936 /* win_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win_util.h; sourceTree = "<group>"; };
8254038C0D92D2CF0006B936 /* wmi_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wmi_util.cc; sourceTree = "<group>"; };
8254038D0D92D2CF0006B936 /* wmi_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wmi_util.h; sourceTree = "<group>"; };
8254038E0D92D2CF0006B936 /* word_iterator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = word_iterator.cc; sourceTree = "<group>"; };
8254038F0D92D2CF0006B936 /* word_iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = word_iterator.h; sourceTree = "<group>"; };
825403B10D92D2E50006B936 /* libbase_gfx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libbase_gfx.a; sourceTree = BUILT_PRODUCTS_DIR; };
825403C00D92D31D0006B936 /* bitmap_header.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bitmap_header.cc; sourceTree = "<group>"; };
825403C10D92D31D0006B936 /* bitmap_header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap_header.h; sourceTree = "<group>"; };
825403C20D92D31D0006B936 /* bitmap_platform_device.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bitmap_platform_device.cc; sourceTree = "<group>"; };
825403C30D92D31D0006B936 /* bitmap_platform_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap_platform_device.h; sourceTree = "<group>"; };
825403C40D92D31D0006B936 /* font_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font_utils.cc; sourceTree = "<group>"; };
825403C50D92D31D0006B936 /* font_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font_utils.h; sourceTree = "<group>"; };
825403C60D92D31D0006B936 /* image_resizer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image_resizer.cc; sourceTree = "<group>"; };
825403C70D92D31D0006B936 /* image_resizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image_resizer.h; sourceTree = "<group>"; };
825403C80D92D31D0006B936 /* native_theme.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = native_theme.cc; sourceTree = "<group>"; };
825403C90D92D31D0006B936 /* native_theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = native_theme.h; sourceTree = "<group>"; };
825403CA0D92D31D0006B936 /* platform_canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_canvas.h; sourceTree = "<group>"; };
825403CB0D92D31D0006B936 /* platform_device.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform_device.cc; sourceTree = "<group>"; };
825403CC0D92D31D0006B936 /* platform_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_device.h; sourceTree = "<group>"; };
825403CD0D92D31D0006B936 /* png_decoder.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = png_decoder.cc; sourceTree = "<group>"; };
825403CE0D92D31D0006B936 /* png_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = png_decoder.h; sourceTree = "<group>"; };
825403CF0D92D31D0006B936 /* png_encoder.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = png_encoder.cc; sourceTree = "<group>"; };
825403D00D92D31D0006B936 /* png_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = png_encoder.h; sourceTree = "<group>"; };
825403D10D92D31D0006B936 /* point.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = point.cc; sourceTree = "<group>"; };
825403D20D92D31D0006B936 /* point.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = point.h; sourceTree = "<group>"; };
825403D30D92D31D0006B936 /* rect_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rect_unittest.cc; sourceTree = "<group>"; };
825403D40D92D31D0006B936 /* rect.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rect.cc; sourceTree = "<group>"; };
825403D50D92D31D0006B936 /* rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rect.h; sourceTree = "<group>"; };
825403D60D92D31D0006B936 /* size.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = size.cc; sourceTree = "<group>"; };
825403D70D92D31D0006B936 /* size.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = size.h; sourceTree = "<group>"; };
825403D80D92D31D0006B936 /* skia_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skia_utils.cc; sourceTree = "<group>"; };
825403D90D92D31D0006B936 /* skia_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = skia_utils.h; sourceTree = "<group>"; };
825403DA0D92D31D0006B936 /* uniscribe.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uniscribe.cc; sourceTree = "<group>"; };
825403DB0D92D31D0006B936 /* uniscribe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uniscribe.h; sourceTree = "<group>"; };
825403DC0D92D31D0006B936 /* vector_canvas.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector_canvas.cc; sourceTree = "<group>"; };
825403DD0D92D31D0006B936 /* vector_canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector_canvas.h; sourceTree = "<group>"; };
825403DE0D92D31D0006B936 /* vector_device.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector_device.cc; sourceTree = "<group>"; };
825403DF0D92D31D0006B936 /* vector_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector_device.h; sourceTree = "<group>"; };
825403E00D92D31D0006B936 /* platform_canvas.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform_canvas.cc; sourceTree = "<group>"; };
82E23FCB0D9C219600F8B40A /* platform_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_thread.h; sourceTree = "<group>"; };
82E23FCC0D9C219600F8B40A /* platform_thread.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform_thread.cc; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
825402B90D92D0FA0006B936 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
825403AF0D92D2E50006B936 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
825402A80D92D0C60006B936 = {
isa = PBXGroup;
children = (
825402B60D92D0E20006B936 /* base */,
825403B40D92D2EC0006B936 /* base_gfx */,
825402BC0D92D0FA0006B936 /* Products */,
);
sourceTree = "<group>";
};
825402B60D92D0E20006B936 /* base */ = {
isa = PBXGroup;
children = (
825402C50D92D1390006B936 /* base_drag_source.cc */,
825402C60D92D1390006B936 /* base_drag_source.h */,
825402C70D92D1390006B936 /* base_drop_target.cc */,
825402C80D92D1390006B936 /* base_drop_target.h */,
825402C90D92D1390006B936 /* base_paths.cc */,
825402CA0D92D1390006B936 /* base_paths.h */,
825402CB0D92D1390006B936 /* base_switches.cc */,
825402CC0D92D1390006B936 /* base_switches.h */,
825402CD0D92D1390006B936 /* basictypes.h */,
825402D70D92D15E0006B936 /* blapi.h */,
825402D80D92D15E0006B936 /* blapit.h */,
825402DB0D92D1730006B936 /* clipboard.h */,
825402DC0D92D1730006B936 /* clipboard.cc */,
825402DD0D92D1730006B936 /* clipboard_util.h */,
825402DE0D92D1730006B936 /* clipboard_util.cc */,
825402E40D92D1850006B936 /* command_line.h */,
825402E30D92D1850006B936 /* command_line.cc */,
825402EB0D92D1940006B936 /* condition_variable.h */,
825402EC0D92D1940006B936 /* condition_variable.cc */,
825402ED0D92D1940006B936 /* condition_variable_events.h */,
825402F30D92D1AC0006B936 /* debug_on_start.h */,
825402F40D92D1AC0006B936 /* debug_on_start.cc */,
825402F10D92D1AC0006B936 /* debug_util.h */,
825402F20D92D1AC0006B936 /* debug_util.cc */,
825402FF0D92D1BC0006B936 /* event_recorder.cc */,
825403000D92D1BC0006B936 /* event_recorder.h */,
825403030D92D1C50006B936 /* file_util.h */,
825403040D92D1C50006B936 /* file_util.cc */,
825403070D92D1CD0006B936 /* file_version_info.h */,
825403080D92D1CD0006B936 /* file_version_info.cc */,
8254030B0D92D1D10006B936 /* fix_wp64.h */,
8254030D0D92D1DB0006B936 /* fixed_string.h */,
8254030F0D92D1E80006B936 /* iat_patch.cc */,
825403100D92D1E80006B936 /* iat_patch.h */,
825403110D92D1E80006B936 /* icu_util.cc */,
825403120D92D1E80006B936 /* icu_util.h */,
825403130D92D1E80006B936 /* id_map.h */,
825403190D92D1F40006B936 /* image_util.cc */,
8254031A0D92D1F40006B936 /* image_util.h */,
8254031B0D92D1F40006B936 /* json_reader.cc */,
8254031C0D92D1F40006B936 /* json_reader.h */,
8254031D0D92D1F40006B936 /* json_writer.cc */,
8254031E0D92D1F40006B936 /* json_writer.h */,
825403250D92D2090006B936 /* lock.cc */,
825403260D92D2090006B936 /* lock.h */,
7BEFC29C0D99832D000829AD /* lock_impl.h */,
7BEFC29D0D99832D000829AD /* lock_impl_mac.cc */,
825403270D92D2090006B936 /* logging.cc */,
825403280D92D2090006B936 /* logging.h */,
825403290D92D2090006B936 /* md5.cc */,
8254032A0D92D2090006B936 /* md5.h */,
8254032B0D92D2090006B936 /* memory_debug.cc */,
8254032C0D92D2090006B936 /* memory_debug.h */,
825403350D92D2110006B936 /* message_loop.cc */,
825403360D92D2110006B936 /* message_loop.h */,
825403390D92D2210006B936 /* observer_list.h */,
8254033A0D92D2210006B936 /* path_service.cc */,
8254033B0D92D2210006B936 /* path_service.h */,
8254033C0D92D2210006B936 /* pe_image.cc */,
8254033D0D92D2210006B936 /* pe_image.h */,
8254033E0D92D2210006B936 /* pickle.cc */,
8254033F0D92D2210006B936 /* pickle.h */,
82E23FCB0D9C219600F8B40A /* platform_thread.h */,
82E23FCC0D9C219600F8B40A /* platform_thread.cc */,
825403400D92D2210006B936 /* port.h */,
825403490D92D23C0006B936 /* prtypes.h */,
825403510D92D24D0006B936 /* process_util.h */,
825403520D92D24D0006B936 /* process_util.cc */,
8254034A0D92D23C0006B936 /* prtime.h */,
8254034B0D92D23C0006B936 /* prtime.cc */,
8254034C0D92D23C0006B936 /* prcpucfg.h */,
7BEB81100D9AD288009BA8DD /* prcpucfg_mac.h */,
825403550D92D2580006B936 /* pure.h */,
825403570D92D25E0006B936 /* pure_api.c */,
825403590D92D27C0006B936 /* ref_counted.h */,
8254035A0D92D27C0006B936 /* registry.cc */,
8254035B0D92D27C0006B936 /* registry.h */,
8254035C0D92D27C0006B936 /* resource_util.cc */,
8254035D0D92D27C0006B936 /* resource_util.h */,
8254035E0D92D27C0006B936 /* revocable_store.cc */,
8254035F0D92D27C0006B936 /* revocable_store.h */,
7B5AD60D0D9DD8050012BCF1 /* scoped_cftyperef.h */,
825403610D92D27C0006B936 /* scoped_ptr.h */,
825403620D92D27C0006B936 /* sha2.cc */,
825403630D92D27C0006B936 /* sha2.h */,
8254036F0D92D2840006B936 /* sha256.h */,
825403700D92D2840006B936 /* sha512.cc */,
825403730D92D2CF0006B936 /* shared_event.cc */,
825403740D92D2CF0006B936 /* shared_event.h */,
825403750D92D2CF0006B936 /* shared_memory.cc */,
825403760D92D2CF0006B936 /* shared_memory.h */,
7BD9E84E0DA447F800FC7A01 /* singleton.h */,
825403770D92D2CF0006B936 /* stack_container.h */,
825403780D92D2CF0006B936 /* stats_counters.h */,
825403790D92D2CF0006B936 /* stats_table.cc */,
8254037A0D92D2CF0006B936 /* stats_table.h */,
8254037B0D92D2CF0006B936 /* string_tokenizer.h */,
8254037C0D92D2CF0006B936 /* string_util.cc */,
8254037D0D92D2CF0006B936 /* string_util.h */,
7BEB834D0D9C4BE0009BA8DD /* string_util_mac.cc */,
7BEE52C10D9D84FD0067FF23 /* string_util_mac.h */,
821B91680DAABD7F00F350D7 /* string16.h */,
8254037E0D92D2CF0006B936 /* task.h */,
8254037F0D92D2CF0006B936 /* thread.cc */,
825403800D92D2CF0006B936 /* thread.h */,
825403810D92D2CF0006B936 /* thread_local_storage.cc */,
825403820D92D2CF0006B936 /* thread_local_storage.h */,
825403830D92D2CF0006B936 /* time.cc */,
825403840D92D2CF0006B936 /* time.h */,
7BEB81490D9B0F33009BA8DD /* time_mac.cc */,
825403850D92D2CF0006B936 /* timer.cc */,
825403860D92D2CF0006B936 /* timer.h */,
825403870D92D2CF0006B936 /* tuple.h */,
825403880D92D2CF0006B936 /* values.cc */,
825403890D92D2CF0006B936 /* values.h */,
8254038A0D92D2CF0006B936 /* win_util.cc */,
8254038B0D92D2CF0006B936 /* win_util.h */,
8254038C0D92D2CF0006B936 /* wmi_util.cc */,
8254038D0D92D2CF0006B936 /* wmi_util.h */,
8254038E0D92D2CF0006B936 /* word_iterator.cc */,
8254038F0D92D2CF0006B936 /* word_iterator.h */,
);
name = base;
sourceTree = "<group>";
};
825402BC0D92D0FA0006B936 /* Products */ = {
isa = PBXGroup;
children = (
825402BB0D92D0FA0006B936 /* libbase.a */,
825403B10D92D2E50006B936 /* libbase_gfx.a */,
);
name = Products;
sourceTree = "<group>";
};
825403B40D92D2EC0006B936 /* base_gfx */ = {
isa = PBXGroup;
children = (
825403C00D92D31D0006B936 /* bitmap_header.cc */,
825403C10D92D31D0006B936 /* bitmap_header.h */,
825403C20D92D31D0006B936 /* bitmap_platform_device.cc */,
825403C30D92D31D0006B936 /* bitmap_platform_device.h */,
825403C40D92D31D0006B936 /* font_utils.cc */,
825403C50D92D31D0006B936 /* font_utils.h */,
825403C60D92D31D0006B936 /* image_resizer.cc */,
825403C70D92D31D0006B936 /* image_resizer.h */,
825403C80D92D31D0006B936 /* native_theme.cc */,
825403C90D92D31D0006B936 /* native_theme.h */,
825403CA0D92D31D0006B936 /* platform_canvas.h */,
825403CB0D92D31D0006B936 /* platform_device.cc */,
825403CC0D92D31D0006B936 /* platform_device.h */,
825403CD0D92D31D0006B936 /* png_decoder.cc */,
825403CE0D92D31D0006B936 /* png_decoder.h */,
825403CF0D92D31D0006B936 /* png_encoder.cc */,
825403D00D92D31D0006B936 /* png_encoder.h */,
825403D10D92D31D0006B936 /* point.cc */,
825403D20D92D31D0006B936 /* point.h */,
825403D30D92D31D0006B936 /* rect_unittest.cc */,
825403D40D92D31D0006B936 /* rect.cc */,
825403D50D92D31D0006B936 /* rect.h */,
825403D60D92D31D0006B936 /* size.cc */,
825403D70D92D31D0006B936 /* size.h */,
825403D80D92D31D0006B936 /* skia_utils.cc */,
825403D90D92D31D0006B936 /* skia_utils.h */,
825403DA0D92D31D0006B936 /* uniscribe.cc */,
825403DB0D92D31D0006B936 /* uniscribe.h */,
825403DC0D92D31D0006B936 /* vector_canvas.cc */,
825403DD0D92D31D0006B936 /* vector_canvas.h */,
825403DE0D92D31D0006B936 /* vector_device.cc */,
825403DF0D92D31D0006B936 /* vector_device.h */,
825403E00D92D31D0006B936 /* platform_canvas.cc */,
);
name = base_gfx;
path = gfx;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
825402B70D92D0FA0006B936 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
825402CF0D92D1390006B936 /* base_drag_source.h in Headers */,
825402D10D92D1390006B936 /* base_drop_target.h in Headers */,
825402D30D92D1390006B936 /* base_paths.h in Headers */,
825402D50D92D1390006B936 /* base_switches.h in Headers */,
825402D60D92D1390006B936 /* basictypes.h in Headers */,
825402D90D92D15E0006B936 /* blapi.h in Headers */,
825402DA0D92D15E0006B936 /* blapit.h in Headers */,
825402DF0D92D1730006B936 /* clipboard.h in Headers */,
825402E10D92D1730006B936 /* clipboard_util.h in Headers */,
825402E60D92D1850006B936 /* command_line.h in Headers */,
825402EE0D92D1940006B936 /* condition_variable.h in Headers */,
825402F00D92D1940006B936 /* condition_variable_events.h in Headers */,
825402F50D92D1AC0006B936 /* debug_util.h in Headers */,
825402F70D92D1AC0006B936 /* debug_on_start.h in Headers */,
825403020D92D1BC0006B936 /* event_recorder.h in Headers */,
825403050D92D1C50006B936 /* file_util.h in Headers */,
825403090D92D1CD0006B936 /* file_version_info.h in Headers */,
8254030C0D92D1D10006B936 /* fix_wp64.h in Headers */,
8254030E0D92D1DB0006B936 /* fixed_string.h in Headers */,
825403150D92D1E80006B936 /* iat_patch.h in Headers */,
825403170D92D1E80006B936 /* icu_util.h in Headers */,
825403180D92D1E80006B936 /* id_map.h in Headers */,
825403200D92D1F40006B936 /* image_util.h in Headers */,
825403220D92D1F40006B936 /* json_reader.h in Headers */,
825403240D92D1F40006B936 /* json_writer.h in Headers */,
8254032E0D92D2090006B936 /* lock.h in Headers */,
7BEFC29E0D99832D000829AD /* lock_impl.h in Headers */,
825403300D92D2090006B936 /* logging.h in Headers */,
825403320D92D2090006B936 /* md5.h in Headers */,
825403340D92D2090006B936 /* memory_debug.h in Headers */,
825403380D92D2110006B936 /* message_loop.h in Headers */,
825403410D92D2210006B936 /* observer_list.h in Headers */,
825403430D92D2210006B936 /* path_service.h in Headers */,
825403450D92D2210006B936 /* pe_image.h in Headers */,
825403470D92D2210006B936 /* pickle.h in Headers */,
82E23FCD0D9C219600F8B40A /* platform_thread.h in Headers */,
825403480D92D2210006B936 /* port.h in Headers */,
8254034D0D92D23C0006B936 /* prtypes.h in Headers */,
8254034E0D92D23C0006B936 /* prtime.h in Headers */,
825403500D92D23C0006B936 /* prcpucfg.h in Headers */,
7BEB81110D9AD288009BA8DD /* prcpucfg_mac.h in Headers */,
825403530D92D24D0006B936 /* process_util.h in Headers */,
825403560D92D2580006B936 /* pure.h in Headers */,
825403640D92D27C0006B936 /* ref_counted.h in Headers */,
825403660D92D27C0006B936 /* registry.h in Headers */,
825403680D92D27C0006B936 /* resource_util.h in Headers */,
8254036A0D92D27C0006B936 /* revocable_store.h in Headers */,
7B5AD60E0D9DD8050012BCF1 /* scoped_cftyperef.h in Headers */,
8254036C0D92D27C0006B936 /* scoped_ptr.h in Headers */,
8254036E0D92D27C0006B936 /* sha2.h in Headers */,
825403710D92D2840006B936 /* sha256.h in Headers */,
825403910D92D2CF0006B936 /* shared_event.h in Headers */,
825403930D92D2CF0006B936 /* shared_memory.h in Headers */,
7BD9E84F0DA447F800FC7A01 /* singleton.h in Headers */,
825403940D92D2CF0006B936 /* stack_container.h in Headers */,
825403950D92D2CF0006B936 /* stats_counters.h in Headers */,
825403970D92D2CF0006B936 /* stats_table.h in Headers */,
825403980D92D2CF0006B936 /* string_tokenizer.h in Headers */,
8254039A0D92D2CF0006B936 /* string_util.h in Headers */,
7BEE52C20D9D84FD0067FF23 /* string_util_mac.h in Headers */,
821B91690DAABD7F00F350D7 /* string16.h in Headers */,
8254039B0D92D2CF0006B936 /* task.h in Headers */,
8254039D0D92D2CF0006B936 /* thread.h in Headers */,
8254039F0D92D2CF0006B936 /* thread_local_storage.h in Headers */,
825403A10D92D2CF0006B936 /* time.h in Headers */,
825403A30D92D2CF0006B936 /* timer.h in Headers */,
825403A40D92D2CF0006B936 /* tuple.h in Headers */,
825403A60D92D2CF0006B936 /* values.h in Headers */,
825403A80D92D2CF0006B936 /* win_util.h in Headers */,
825403AA0D92D2CF0006B936 /* wmi_util.h in Headers */,
825403AC0D92D2CF0006B936 /* word_iterator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
825403AD0D92D2E50006B936 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
825403E20D92D31D0006B936 /* bitmap_header.h in Headers */,
825403E40D92D31D0006B936 /* bitmap_platform_device.h in Headers */,
825403E60D92D31D0006B936 /* font_utils.h in Headers */,
825403E80D92D31D0006B936 /* image_resizer.h in Headers */,
825403EA0D92D31D0006B936 /* native_theme.h in Headers */,
825403EB0D92D31D0006B936 /* platform_canvas.h in Headers */,
825403ED0D92D31D0006B936 /* platform_device.h in Headers */,
825403EF0D92D31D0006B936 /* png_decoder.h in Headers */,
825403F10D92D31D0006B936 /* png_encoder.h in Headers */,
825403F30D92D31D0006B936 /* point.h in Headers */,
825403F60D92D31D0006B936 /* rect.h in Headers */,
825403F80D92D31D0006B936 /* size.h in Headers */,
825403FA0D92D31D0006B936 /* skia_utils.h in Headers */,
825403FC0D92D31D0006B936 /* uniscribe.h in Headers */,
825403FE0D92D31D0006B936 /* vector_canvas.h in Headers */,
825404000D92D31D0006B936 /* vector_device.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
825402BA0D92D0FA0006B936 /* base */ = {
isa = PBXNativeTarget;
buildConfigurationList = 825402BF0D92D0FB0006B936 /* Build configuration list for PBXNativeTarget "base" */;
buildPhases = (
825402B70D92D0FA0006B936 /* Headers */,
825402B80D92D0FA0006B936 /* Sources */,
825402B90D92D0FA0006B936 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = base;
productName = base;
productReference = 825402BB0D92D0FA0006B936 /* libbase.a */;
productType = "com.apple.product-type.library.static";
};
825403B00D92D2E50006B936 /* base_gfx */ = {
isa = PBXNativeTarget;
buildConfigurationList = 825403B50D92D2EC0006B936 /* Build configuration list for PBXNativeTarget "base_gfx" */;
buildPhases = (
825403AD0D92D2E50006B936 /* Headers */,
825403AE0D92D2E50006B936 /* Sources */,
825403AF0D92D2E50006B936 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = base_gfx;
productName = base_gfx;
productReference = 825403B10D92D2E50006B936 /* libbase_gfx.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
825402AA0D92D0C60006B936 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 825402AD0D92D0C60006B936 /* Build configuration list for PBXProject "base" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 0;
mainGroup = 825402A80D92D0C60006B936;
productRefGroup = 825402BC0D92D0FA0006B936 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
825402BA0D92D0FA0006B936 /* base */,
825403B00D92D2E50006B936 /* base_gfx */,
825404020D92D3340006B936 /* All */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
825402B80D92D0FA0006B936 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
825402CE0D92D1390006B936 /* base_drag_source.cc in Sources */,
825402D00D92D1390006B936 /* base_drop_target.cc in Sources */,
825402D20D92D1390006B936 /* base_paths.cc in Sources */,
825402D40D92D1390006B936 /* base_switches.cc in Sources */,
825402E00D92D1730006B936 /* clipboard.cc in Sources */,
825402E20D92D1730006B936 /* clipboard_util.cc in Sources */,
825402E50D92D1850006B936 /* command_line.cc in Sources */,
825402EF0D92D1940006B936 /* condition_variable.cc in Sources */,
825402F60D92D1AC0006B936 /* debug_util.cc in Sources */,
825402F80D92D1AC0006B936 /* debug_on_start.cc in Sources */,
825403010D92D1BC0006B936 /* event_recorder.cc in Sources */,
825403060D92D1C50006B936 /* file_util.cc in Sources */,
8254030A0D92D1CD0006B936 /* file_version_info.cc in Sources */,
825403140D92D1E80006B936 /* iat_patch.cc in Sources */,
825403160D92D1E80006B936 /* icu_util.cc in Sources */,
8254031F0D92D1F40006B936 /* image_util.cc in Sources */,
825403210D92D1F40006B936 /* json_reader.cc in Sources */,
825403230D92D1F40006B936 /* json_writer.cc in Sources */,
8254032D0D92D2090006B936 /* lock.cc in Sources */,
7BEFC29F0D99832D000829AD /* lock_impl_mac.cc in Sources */,
8254032F0D92D2090006B936 /* logging.cc in Sources */,
825403310D92D2090006B936 /* md5.cc in Sources */,
825403330D92D2090006B936 /* memory_debug.cc in Sources */,
825403370D92D2110006B936 /* message_loop.cc in Sources */,
825403420D92D2210006B936 /* path_service.cc in Sources */,
825403440D92D2210006B936 /* pe_image.cc in Sources */,
825403460D92D2210006B936 /* pickle.cc in Sources */,
82E23FCE0D9C219600F8B40A /* platform_thread.cc in Sources */,
8254034F0D92D23C0006B936 /* prtime.cc in Sources */,
825403540D92D24D0006B936 /* process_util.cc in Sources */,
825403580D92D25E0006B936 /* pure_api.c in Sources */,
825403650D92D27C0006B936 /* registry.cc in Sources */,
825403670D92D27C0006B936 /* resource_util.cc in Sources */,
825403690D92D27C0006B936 /* revocable_store.cc in Sources */,
8254036D0D92D27C0006B936 /* sha2.cc in Sources */,
825403720D92D2840006B936 /* sha512.cc in Sources */,
825403900D92D2CF0006B936 /* shared_event.cc in Sources */,
825403920D92D2CF0006B936 /* shared_memory.cc in Sources */,
825403960D92D2CF0006B936 /* stats_table.cc in Sources */,
825403990D92D2CF0006B936 /* string_util.cc in Sources */,
7BEB834E0D9C4BE0009BA8DD /* string_util_mac.cc in Sources */,
8254039C0D92D2CF0006B936 /* thread.cc in Sources */,
8254039E0D92D2CF0006B936 /* thread_local_storage.cc in Sources */,
825403A00D92D2CF0006B936 /* time.cc in Sources */,
7BEB814A0D9B0F33009BA8DD /* time_mac.cc in Sources */,
825403A20D92D2CF0006B936 /* timer.cc in Sources */,
825403A50D92D2CF0006B936 /* values.cc in Sources */,
825403A70D92D2CF0006B936 /* win_util.cc in Sources */,
825403A90D92D2CF0006B936 /* wmi_util.cc in Sources */,
825403AB0D92D2CF0006B936 /* word_iterator.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
825403AE0D92D2E50006B936 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
825403E10D92D31D0006B936 /* bitmap_header.cc in Sources */,
825403E30D92D31D0006B936 /* bitmap_platform_device.cc in Sources */,
825403E50D92D31D0006B936 /* font_utils.cc in Sources */,
825403E70D92D31D0006B936 /* image_resizer.cc in Sources */,
825403E90D92D31D0006B936 /* native_theme.cc in Sources */,
825403EC0D92D31D0006B936 /* platform_device.cc in Sources */,
825403EE0D92D31D0006B936 /* png_decoder.cc in Sources */,
825403F00D92D31D0006B936 /* png_encoder.cc in Sources */,
825403F20D92D31D0006B936 /* point.cc in Sources */,
825403F40D92D31D0006B936 /* rect_unittest.cc in Sources */,
825403F50D92D31D0006B936 /* rect.cc in Sources */,
825403F70D92D31D0006B936 /* size.cc in Sources */,
825403F90D92D31D0006B936 /* skia_utils.cc in Sources */,
825403FB0D92D31D0006B936 /* uniscribe.cc in Sources */,
825403FD0D92D31D0006B936 /* vector_canvas.cc in Sources */,
825403FF0D92D31D0006B936 /* vector_device.cc in Sources */,
825404010D92D31D0006B936 /* platform_canvas.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
825404060D92D33A0006B936 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 825402BA0D92D0FA0006B936 /* base */;
targetProxy = 825404050D92D33A0006B936 /* PBXContainerItemProxy */;
};
825404080D92D33C0006B936 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 825403B00D92D2E50006B936 /* base_gfx */;
targetProxy = 825404070D92D33C0006B936 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
825402AB0D92D0C60006B936 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_CW_ASM_SYNTAX = NO;
GCC_ENABLE_PASCAL_STRINGS = NO;
GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
USE_HEADERMAP = NO;
WARNING_CFLAGS = "-Wall";
};
name = Debug;
};
825402AC0D92D0C60006B936 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
GCC_CW_ASM_SYNTAX = NO;
GCC_ENABLE_PASCAL_STRINGS = NO;
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
USE_HEADERMAP = NO;
WARNING_CFLAGS = "-Wall";
};
name = Release;
};
825402BD0D92D0FB0006B936 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
HEADER_SEARCH_PATHS = (
..,
../third_party/icu38/public/common,
../third_party/icu38/public/i18n,
);
PREBINDING = NO;
PRODUCT_NAME = base;
};
name = Debug;
};
825402BE0D92D0FB0006B936 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_DYNAMIC_NO_PIC = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
HEADER_SEARCH_PATHS = (
..,
../third_party/icu38/public/common,
../third_party/icu38/public/i18n,
);
PREBINDING = NO;
PRODUCT_NAME = base;
};
name = Release;
};
825403B20D92D2E50006B936 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
PREBINDING = NO;
PRODUCT_NAME = base_gfx;
};
name = Debug;
};
825403B30D92D2E50006B936 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_DYNAMIC_NO_PIC = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
PREBINDING = NO;
PRODUCT_NAME = base_gfx;
};
name = Release;
};
825404030D92D3340006B936 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
PRODUCT_NAME = All;
};
name = Debug;
};
825404040D92D3340006B936 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_FIX_AND_CONTINUE = NO;
PRODUCT_NAME = All;
ZERO_LINK = NO;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
825402AD0D92D0C60006B936 /* Build configuration list for PBXProject "base" */ = {
isa = XCConfigurationList;
buildConfigurations = (
825402AB0D92D0C60006B936 /* Debug */,
825402AC0D92D0C60006B936 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
825402BF0D92D0FB0006B936 /* Build configuration list for PBXNativeTarget "base" */ = {
isa = XCConfigurationList;
buildConfigurations = (
825402BD0D92D0FB0006B936 /* Debug */,
825402BE0D92D0FB0006B936 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
825403B50D92D2EC0006B936 /* Build configuration list for PBXNativeTarget "base_gfx" */ = {
isa = XCConfigurationList;
buildConfigurations = (
825403B20D92D2E50006B936 /* Debug */,
825403B30D92D2E50006B936 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
825404110D92D35C0006B936 /* Build configuration list for PBXAggregateTarget "All" */ = {
isa = XCConfigurationList;
buildConfigurations = (
825404030D92D3340006B936 /* Debug */,
825404040D92D3340006B936 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 825402AA0D92D0C60006B936 /* Project object */;
}

88
base/base_drag_source.cc Normal file

@ -0,0 +1,88 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <atlbase.h>
#include "base/base_drag_source.h"
///////////////////////////////////////////////////////////////////////////////
// BaseDragSource, public:
BaseDragSource::BaseDragSource() : ref_count_(0) {
}
///////////////////////////////////////////////////////////////////////////////
// BaseDragSource, IDropSource implementation:
HRESULT BaseDragSource::QueryContinueDrag(BOOL escape_pressed,
DWORD key_state) {
if (escape_pressed) {
OnDragSourceCancel();
return DRAGDROP_S_CANCEL;
}
if (!(key_state & MK_LBUTTON)) {
OnDragSourceDrop();
return DRAGDROP_S_DROP;
}
OnDragSourceMove();
return S_OK;
}
HRESULT BaseDragSource::GiveFeedback(DWORD effect) {
return DRAGDROP_S_USEDEFAULTCURSORS;
}
///////////////////////////////////////////////////////////////////////////////
// BaseDragSource, IUnknown implementation:
HRESULT BaseDragSource::QueryInterface(const IID& iid, void** object) {
*object = NULL;
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDropSource)) {
*object = this;
} else {
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG BaseDragSource::AddRef() {
return InterlockedIncrement(&ref_count_);
}
ULONG BaseDragSource::Release() {
if (InterlockedDecrement(&ref_count_) == 0) {
ULONG copied_refcnt = ref_count_;
delete this;
return copied_refcnt;
}
return ref_count_;
}

71
base/base_drag_source.h Normal file

@ -0,0 +1,71 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_BASE_DRAG_SOURCE_H__
#define BASE_BASE_DRAG_SOURCE_H__
#include <objidl.h>
#include "base/basictypes.h"
///////////////////////////////////////////////////////////////////////////////
//
// BaseDragSource
//
// A base IDropSource implementation. Handles notifications sent by an active
// drag-drop operation as the user mouses over other drop targets on their
// system. This object tells Windows whether or not the drag should continue,
// and supplies the appropriate cursors.
//
class BaseDragSource : public IDropSource {
public:
BaseDragSource();
virtual ~BaseDragSource() { }
// IDropSource implementation:
HRESULT __stdcall QueryContinueDrag(BOOL escape_pressed, DWORD key_state);
HRESULT __stdcall GiveFeedback(DWORD effect);
// IUnknown implementation:
HRESULT __stdcall QueryInterface(const IID& iid, void** object);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
protected:
virtual void OnDragSourceCancel() { }
virtual void OnDragSourceDrop() { }
virtual void OnDragSourceMove() { }
private:
LONG ref_count_;
DISALLOW_EVIL_CONSTRUCTORS(BaseDragSource);
};
#endif // #ifndef BASE_DRAG_SOURCE_H__

187
base/base_drop_target.cc Normal file

@ -0,0 +1,187 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windows.h>
#include <shlobj.h>
#include "base/base_drop_target.h"
#include "base/logging.h"
///////////////////////////////////////////////////////////////////////////////
IDropTargetHelper* BaseDropTarget::cached_drop_target_helper_ = NULL;
BaseDropTarget::BaseDropTarget(HWND hwnd)
: suspend_(false),
ref_count_(0),
hwnd_(hwnd) {
DCHECK(hwnd);
HRESULT result = RegisterDragDrop(hwnd, this);
}
BaseDropTarget::~BaseDropTarget() {
}
// static
IDropTargetHelper* BaseDropTarget::DropHelper() {
if (!cached_drop_target_helper_) {
CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
IID_IDropTargetHelper,
reinterpret_cast<void**>(&cached_drop_target_helper_));
}
return cached_drop_target_helper_;
}
///////////////////////////////////////////////////////////////////////////////
// BaseDropTarget, IDropTarget implementation:
HRESULT BaseDropTarget::DragEnter(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
// Tell the helper that we entered so it can update the drag image.
IDropTargetHelper* drop_helper = DropHelper();
if (drop_helper) {
drop_helper->DragEnter(GetHWND(), data_object,
reinterpret_cast<POINT*>(&cursor_position), *effect);
}
// You can't drag and drop within the same HWND.
if (suspend_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
current_data_object_ = data_object;
POINT screen_pt = { cursor_position.x, cursor_position.y };
*effect = OnDragEnter(current_data_object_, key_state, screen_pt, *effect);
return S_OK;
}
HRESULT BaseDropTarget::DragOver(DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
// Tell the helper that we moved over it so it can update the drag image.
IDropTargetHelper* drop_helper = DropHelper();
if (drop_helper)
drop_helper->DragOver(reinterpret_cast<POINT*>(&cursor_position), *effect);
if (suspend_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
POINT screen_pt = { cursor_position.x, cursor_position.y };
*effect = OnDragOver(current_data_object_, key_state, screen_pt, *effect);
return S_OK;
}
HRESULT BaseDropTarget::DragLeave() {
// Tell the helper that we moved out of it so it can update the drag image.
IDropTargetHelper* drop_helper = DropHelper();
if (drop_helper)
drop_helper->DragLeave();
OnDragLeave(current_data_object_);
current_data_object_ = NULL;
return S_OK;
}
HRESULT BaseDropTarget::Drop(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
// Tell the helper that we dropped onto it so it can update the drag image.
IDropTargetHelper* drop_helper = DropHelper();
if (drop_helper) {
drop_helper->Drop(current_data_object_,
reinterpret_cast<POINT*>(&cursor_position), *effect);
}
if (suspend_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
POINT screen_pt = { cursor_position.x, cursor_position.y };
*effect = OnDrop(current_data_object_, key_state, screen_pt, *effect);
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// BaseDropTarget, IUnknown implementation:
HRESULT BaseDropTarget::QueryInterface(const IID& iid, void** object) {
*object = NULL;
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDropTarget)) {
*object = this;
} else {
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG BaseDropTarget::AddRef() {
return InterlockedIncrement(&ref_count_);
}
ULONG BaseDropTarget::Release() {
if (InterlockedDecrement(&ref_count_) == 0) {
ULONG copied_refcnt = ref_count_;
delete this;
return copied_refcnt;
}
return ref_count_;
}
DWORD BaseDropTarget::OnDragEnter(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect) {
return DROPEFFECT_NONE;
}
DWORD BaseDropTarget::OnDragOver(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect) {
return DROPEFFECT_NONE;
}
void BaseDropTarget::OnDragLeave(IDataObject* data_object) {
}
DWORD BaseDropTarget::OnDrop(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect) {
return DROPEFFECT_NONE;
}

142
base/base_drop_target.h Normal file

@ -0,0 +1,142 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_BASE_DROP_TARGET_H__
#define BASE_BASE_DROP_TARGET_H__
#include <atlbase.h>
#include <objidl.h>
#include <shobjidl.h>
#include "base/basictypes.h"
// A DropTarget implementation that takes care of the nitty gritty
// of dnd. While this class is concrete, subclasses will most likely
// want to override various OnXXX methods.
//
// Because BaseDropTarget is ref counted you shouldn't delete it directly,
// rather wrap it in a scoped_refptr. Be sure and invoke RevokeDragDrop(m_hWnd)
// before the HWND is deleted too.
class BaseDropTarget : public IDropTarget {
public:
// Create a new BaseDropTarget associating it with the given HWND.
explicit BaseDropTarget(HWND hwnd);
virtual ~BaseDropTarget();
// When suspend is set to |true|, the drop target does not receive drops from
// drags initiated within the owning HWND.
// TODO(beng): (http://b/1085385) figure out how we will handle legitimate
// drag-drop operations within the same HWND, such as dragging
// selected text to an edit field.
void set_suspend(bool suspend) { suspend_ = suspend; }
// IDropTarget implementation:
HRESULT __stdcall DragEnter(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect);
HRESULT __stdcall DragOver(DWORD key_state,
POINTL cursor_position,
DWORD* effect);
HRESULT __stdcall DragLeave();
HRESULT __stdcall Drop(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect);
// IUnknown implementation:
HRESULT __stdcall QueryInterface(const IID& iid, void** object);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
protected:
// Returns the hosting HWND.
HWND GetHWND() { return hwnd_; }
// Invoked when the cursor first moves over the hwnd during a dnd session.
// This should return a bitmask of the supported drop operations:
// DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_LINK and/or
// DROPEFFECT_MOVE.
virtual DWORD OnDragEnter(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect);
// Invoked when the cursor moves over the window during a dnd session.
// This should return a bitmask of the supported drop operations:
// DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_LINK and/or
// DROPEFFECT_MOVE.
virtual DWORD OnDragOver(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect);
// Invoked when the cursor moves outside the bounds of the hwnd during a
// dnd session.
virtual void OnDragLeave(IDataObject* data_object);
// Invoked when the drop ends on the window. This should return the operation
// that was taken.
virtual DWORD OnDrop(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect);
private:
// Returns the cached drop helper, creating one if necessary. The returned
// object is not addrefed. May return NULL if the object couldn't be created.
static IDropTargetHelper* DropHelper();
// The data object currently being dragged over this drop target.
CComPtr<IDataObject> current_data_object_;
// A helper object that is used to provide drag image support while the mouse
// is dragging over the content area.
//
// DO NOT ACCESS DIRECTLY! Use DropHelper() instead, which will lazily create
// this if it doesn't exist yet. This object can take tens of milliseconds to
// create, and we don't want to block any window opening for this, especially
// since often, DnD will never be used. Instead, we force this penalty to the
// first time it is actually used.
static IDropTargetHelper* cached_drop_target_helper_;
// The HWND of the source. This HWND is used to determine coordinates for
// mouse events that are sent to the renderer notifying various drag states.
HWND hwnd_;
// Whether or not we are currently processing drag notifications for drags
// initiated in this window.
bool suspend_;
LONG ref_count_;
DISALLOW_EVIL_CONSTRUCTORS(BaseDropTarget);
};
#endif // BASE_BASE_DROP_TARGET_H__

151
base/base_paths.cc Normal file

@ -0,0 +1,151 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/base_paths.h"
#include <shlobj.h>
#include "base/file_util.h"
#include "base/path_service.h"
// This is here for the sole purpose of looking up the corresponding HMODULE.
static int handle_lookup = 0;
namespace base {
bool PathProvider(int key, std::wstring* result) {
// NOTE: DIR_CURRENT is a special cased in PathService::Get
// We need to go compute the value. It would be nice to support paths with
// names longer than MAX_PATH, but the system functions don't seem to be
// designed for it either, with the exception of GetTempPath (but other
// things will surely break if the temp path is too long, so we don't bother
// handling it.
wchar_t system_buffer[MAX_PATH];
system_buffer[0] = 0;
std::wstring cur;
switch (key) {
case base::FILE_EXE:
GetModuleFileName(NULL, system_buffer, MAX_PATH);
cur = system_buffer;
break;
case base::FILE_MODULE: {
// the resource containing module is assumed to be the one that
// this code lives in, whether that's a dll or exe
MEMORY_BASIC_INFORMATION info = { 0 };
VirtualQuery(reinterpret_cast<void*>(&handle_lookup),
&info, sizeof(info));
// Module handles are just the allocation base address of the module.
HMODULE this_module = reinterpret_cast<HMODULE>(info.AllocationBase);
GetModuleFileName(this_module, system_buffer, MAX_PATH);
cur = system_buffer;
break;
}
case base::DIR_EXE:
PathProvider(base::FILE_EXE, &cur);
file_util::TrimFilename(&cur);
break;
case base::DIR_MODULE:
PathProvider(base::FILE_MODULE, &cur);
file_util::TrimFilename(&cur);
break;
case base::DIR_TEMP:
if (!file_util::GetTempDir(&cur))
return false;
break;
case base::DIR_WINDOWS:
GetWindowsDirectory(system_buffer, MAX_PATH);
cur = system_buffer;
break;
case base::DIR_SYSTEM:
GetSystemDirectory(system_buffer, MAX_PATH);
cur = system_buffer;
break;
case base::DIR_PROGRAM_FILES:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = system_buffer;
break;
case base::DIR_SOURCE_ROOT:
// By default, unit tests execute two levels deep from the source root.
// For example: chrome/{Debug|Release}/ui_tests.exe
PathProvider(base::DIR_EXE, &cur);
file_util::UpOneDirectory(&cur);
file_util::UpOneDirectory(&cur);
break;
case base::DIR_APP_DATA:
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
return false;
cur = system_buffer;
break;
case base::DIR_LOCAL_APP_DATA_LOW:
// TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
return false;
cur = system_buffer;
file_util::UpOneDirectory(&cur);
file_util::AppendToPath(&cur, L"LocalLow");
break;
case base::DIR_LOCAL_APP_DATA:
if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = system_buffer;
break;
case base::DIR_IE_INTERNET_CACHE:
if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = system_buffer;
break;
case base::DIR_COMMON_START_MENU:
if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = system_buffer;
break;
case base::DIR_START_MENU:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = system_buffer;
break;
default:
return false;
}
result->swap(cur);
return true;
}
} // namespace base

70
base/base_paths.h Normal file

@ -0,0 +1,70 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_BASE_PATHS_H__
#define BASE_BASE_PATHS_H__
// This file declares path keys for the base module. These can be used with
// the PathService to access various special directories and files.
namespace base {
enum {
PATH_START = 0,
DIR_CURRENT, // current directory
DIR_EXE, // directory containing FILE_EXE
DIR_MODULE, // directory containing FILE_MODULE
FILE_EXE, // path and filename of the current executable
FILE_MODULE, // path and filename of the module containing the code for the
// PathService (which could differ from FILE_EXE if the
// PathService were compiled into a DLL, for example)
DIR_TEMP, // temporary directory
DIR_WINDOWS, // Windows directory, usually "c:\windows"
DIR_SYSTEM, // Usually c:\windows\system32"
DIR_PROGRAM_FILES, // Usually c:\program files
DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful
// for tests that need to locate various resources. It
// should not be used outside of test code.
DIR_APP_DATA, // Application Data directory under the user profile.
DIR_LOCAL_APP_DATA_LOW, // Local AppData directory for low integrity level.
DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under the
// user profile.
DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory.
DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\
// Start Menu\Programs"
DIR_START_MENU, // Usually "C:\Documents and Settings\<user>\
// Start Menu\Programs"
PATH_END
};
} // namespace base
#endif // BASE_BASE_PATHS_H__

58
base/base_switches.cc Normal file

@ -0,0 +1,58 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/base_switches.h"
namespace switches {
// If the program includes chrome/common/debug_on_start.h, the process will
// start the JIT system-registered debugger on itself and will wait for 60
// seconds for the debugger to attach to itself. Then a break point will be hit.
const wchar_t kDebugOnStart[] = L"debug-on-start";
// Will wait for 60 seconds for a debugger to come to attach to the process.
const wchar_t kWaitForDebugger[] = L"wait-for-debugger";
// Suppresses all error dialogs when present.
const wchar_t kNoErrorDialogs[] = L"noerrdialogs";
// Disables the crash reporting.
const wchar_t kDisableBreakpad[] = L"disable-breakpad";
// Generates full memory crash dump.
const wchar_t kFullMemoryCrashReport[] = L"full-memory-crash-report";
// The value of this switch determines whether the process is started as a
// renderer or plugin host. If it's empty, it's the browser.
const wchar_t kProcessType[] = L"type";
// Enable DCHECKs in release mode.
const wchar_t kEnableDCHECK[] = L"enable-dcheck";
} // namespace switches

47
base/base_switches.h Normal file

@ -0,0 +1,47 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Defines all the "base" command-line switches.
#ifndef BASE_SWITCHES_H__
#define BASE_SWITCHES_H__
namespace switches {
extern const wchar_t kDebugOnStart[];
extern const wchar_t kWaitForDebugger[];
extern const wchar_t kDisableBreakpad[];
extern const wchar_t kFullMemoryCrashReport[];
extern const wchar_t kNoErrorDialogs[];
extern const wchar_t kProcessType[];
extern const wchar_t kEnableDCHECK[];
} // namespace switches
#endif // CHROME_COMMON_CHROME_SWITCHES_H__

403
base/basictypes.h Normal file

@ -0,0 +1,403 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Copied from base/basictypes.h with some modifications
#ifndef BASE_BASICTYPES_H__
#define BASE_BASICTYPES_H__
#include <assert.h> // for use with down_cast<>
#include <limits.h> // So we can set the bounds of our types
#include <stddef.h> // For size_t
#include <string.h> // for memcpy
#include "base/port.h" // Types that only need exist on certain systems
typedef signed char schar;
typedef signed char int8;
typedef short int16;
// TODO(mbelshe) Remove these type guards. These are
// temporary to avoid conflicts with npapi.h.
#ifndef _INT32
#define _INT32
typedef int int32;
#endif
typedef long long int64;
// NOTE: unsigned types are DANGEROUS in loops and other arithmetical
// places. Use the signed types unless your variable represents a bit
// pattern (eg a hash value) or you really need the extra bit. Do NOT
// use 'unsigned' to express "this value should always be positive";
// use assertions for this.
typedef unsigned char uint8;
typedef unsigned short uint16;
// TODO(mbelshe) Remove these type guards. These are
// temporary to avoid conflicts with npapi.h.
#ifndef _UINT32
#define _UINT32
typedef unsigned int uint32;
#endif
typedef unsigned long long uint64;
// A type to represent a Unicode code-point value. As of Unicode 4.0,
// such values require up to 21 bits.
// (For type-checking on pointers, make this explicitly signed,
// and it should always be the signed version of whatever int32 is.)
typedef signed int char32;
const uint8 kuint8max = UCHAR_MAX;
const uint16 kuint16max = USHRT_MAX;
const uint32 kuint32max = UINT_MAX;
const uint64 kuint64max = ULLONG_MAX;
const int8 kint8min = SCHAR_MIN;
const int8 kint8max = SCHAR_MAX;
const int16 kint16min = SHRT_MIN;
const int16 kint16max = SHRT_MAX;
const int32 kint32min = INT_MIN;
const int32 kint32max = INT_MAX;
const int64 kint64min = LLONG_MIN;
const int64 kint64max = LLONG_MAX;
// id for odp categories
typedef uint32 CatId;
const CatId kIllegalCatId = static_cast<CatId>(0);
typedef uint32 TermId;
const TermId kIllegalTermId = static_cast<TermId>(0);
typedef uint32 HostId;
const HostId kIllegalHostId = static_cast<HostId>(0);
typedef uint32 DomainId;
const DomainId kIllegalDomainId = static_cast<DomainId>(0);
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// An older, deprecated, politically incorrect name for the above.
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName)
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example. If you use arraysize on
// a pointer by mistake, you will get a compile-time error.
//
// One caveat is that arraysize() doesn't accept any array of an
// anonymous type or a type defined inside a function. In these rare
// cases, you have to use the unsafe ARRAYSIZE() macro below. This is
// due to a limitation in C++'s template system. The limitation might
// eventually be removed, but it hasn't happened yet.
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _MSC_VER
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// ARRAYSIZE performs essentially the same calculation as arraysize,
// but can be used on anonymous types or types defined inside
// functions. It's less safe than arraysize as it accepts some
// (although not all) pointers. Therefore, you should use arraysize
// whenever possible.
//
// The expression ARRAYSIZE(a) is a compile-time constant of type
// size_t.
//
// ARRAYSIZE catches a few type errors. If you see a compiler error
//
// "warning: division by zero in ..."
//
// when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
// You should only use ARRAYSIZE on statically allocated arrays.
//
// The following comments are on the implementation details, and can
// be ignored by the users.
//
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
// the array) and sizeof(*(arr)) (the # of bytes in one array
// element). If the former is divisible by the latter, perhaps arr is
// indeed an array, in which case the division result is the # of
// elements in the array. Otherwise, arr cannot possibly be an array,
// and we generate a compiler error to prevent the code from
// compiling.
//
// Since the size of bool is implementation-defined, we need to cast
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
// result has type size_t.
//
// This macro is not perfect as it wrongfully accepts certain
// pointers, namely where the pointer size is divisible by the pointee
// size. Since all our code has to go through a 32-bit compiler,
// where a pointer is 4 bytes, this means all pointers to a type whose
// size is 3 or greater than 4 will be (righteously) rejected.
#define ARRAYSIZE_UNSAFE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
// Use implicit_cast as a safe version of static_cast or const_cast
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
// a const pointer to Foo).
// When you use implicit_cast, the compiler checks that the cast is safe.
// Such explicit implicit_casts are necessary in surprisingly many
// situations where C++ demands an exact type match instead of an
// argument type convertable to a target type.
//
// The From type can be inferred, so the preferred syntax for using
// implicit_cast is the same as for static_cast etc.:
//
// implicit_cast<ToType>(expr)
//
// implicit_cast would have been part of the C++ standard library,
// but the proposal was submitted too late. It will probably make
// its way into the language in the future.
template<typename To, typename From>
inline To implicit_cast(From const &f) {
return f;
}
// When you upcast (that is, cast a pointer from type Foo to type
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
// always succeed. When you downcast (that is, cast a pointer from
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
// how do you know the pointer is really of type SubclassOfFoo? It
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
// when you downcast, you should use this macro. In debug mode, we
// use dynamic_cast<> to double-check the downcast is legal (we die
// if it's not). In normal mode, we do the efficient static_cast<>
// instead. Thus, it's important to test in debug mode to make sure
// the cast is legal!
// This is the only place in the code we should use dynamic_cast<>.
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
// do RTTI (eg code like this:
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
// You should design the code some other way not to need this.
template<typename To, typename From> // use like this: down_cast<T*>(foo);
inline To down_cast(From* f) { // so we only accept pointers
// Ensures that To is a sub-type of From *. This test is here only
// for compile-time type checking, and has no overhead in an
// optimized build at run-time, as it will be optimized away
// completely.
if (false) {
implicit_cast<From*, To>(0);
}
assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
return static_cast<To>(f);
}
// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
template <bool>
struct CompileAssert {
};
#undef COMPILE_ASSERT
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
// elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
// does not work, as gcc supports variable-length arrays whose sizes
// are determined at run-time (this is gcc's extension and not part
// of the C++ standard). As a result, gcc fails to reject the
// following code with the simple definition:
//
// int foo;
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
//
// instead, these compilers will refuse to compile
//
// COMPILE_ASSERT(5 > 0, some_message);
//
// (They seem to think the ">" in "5 > 0" marks the end of the
// template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
// MetatagId refers to metatag-id that we assign to
// each metatag <name, value> pair..
typedef uint32 MetatagId;
// Argument type used in interfaces that can optionally take ownership
// of a passed in argument. If TAKE_OWNERSHIP is passed, the called
// object takes ownership of the argument. Otherwise it does not.
enum Ownership {
DO_NOT_TAKE_OWNERSHIP,
TAKE_OWNERSHIP
};
// Use these as the mlock_bytes parameter to MLock and MLockGeneral
enum { MLOCK_ALL = -1, MLOCK_NONE = 0 };
// Helper routine to avoid buggy code like the following:
// if (pos + N < end) ...
// If pos is large enough, "pos + N" may overflow. For example,
// pos==0xfffff000 and N==1MB.
//
// This often happens on Nacona's in 32-bit mode, because the
// main thread's stack is put very close to address 0xffffffff.
//
// PointerRangeSize(a,b) returns the size of the range [a,b-1]
inline size_t PointerRangeSize(const char* start, const char* end) {
assert(start <= end);
return end - start;
}
// bit_cast<Dest,Source> is a template function that implements the
// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
// very low-level functions like the protobuf library and fast math
// support.
//
// float f = 3.14159265358979;
// int i = bit_cast<int32>(f);
// // i = 0x40490fdb
//
// The classical address-casting method is:
//
// // WRONG
// float f = 3.14159265358979; // WRONG
// int i = * reinterpret_cast<int*>(&f); // WRONG
//
// The address-casting method actually produces undefined behavior
// according to ISO C++ specification section 3.10 -15 -. Roughly, this
// section says: if an object in memory has one type, and a program
// accesses it with a different type, then the result is undefined
// behavior for most values of "different type".
//
// This is true for any cast syntax, either *(int*)&f or
// *reinterpret_cast<int*>(&f). And it is particularly true for
// conversions betweeen integral lvalues and floating-point lvalues.
//
// The purpose of 3.10 -15- is to allow optimizing compilers to assume
// that expressions with different types refer to different memory. gcc
// 4.0.1 has an optimizer that takes advantage of this. So a
// non-conforming program quietly produces wildly incorrect output.
//
// The problem is not the use of reinterpret_cast. The problem is type
// punning: holding an object in memory of one type and reading its bits
// back using a different type.
//
// The C++ standard is more subtle and complex than this, but that
// is the basic idea.
//
// Anyways ...
//
// bit_cast<> calls memcpy() which is blessed by the standard,
// especially by the example in section 3.9 . Also, of course,
// bit_cast<> wraps up the nasty logic in one place.
//
// Fortunately memcpy() is very fast. In optimized mode, with a
// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
// code with the minimal amount of data movement. On a 32-bit system,
// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
// compiles to two loads and two stores.
//
// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
//
// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
// is likely to surprise you.
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1];
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
#endif // BASE_BASICTYPES_H__

719
base/build/base.vcproj Normal file

@ -0,0 +1,719 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="base"
ProjectGUID="{1832A374-8A74-4F9E-B536-69A699B3E165}"
RootNamespace="base"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\base.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="4"
InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\base.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\atomic.h"
>
</File>
<File
RelativePath="..\base_drag_source.cc"
>
</File>
<File
RelativePath="..\base_drag_source.h"
>
</File>
<File
RelativePath="..\base_drop_target.cc"
>
</File>
<File
RelativePath="..\base_drop_target.h"
>
</File>
<File
RelativePath="..\base_paths.cc"
>
</File>
<File
RelativePath="..\base_paths.h"
>
</File>
<File
RelativePath="..\base_switches.cc"
>
</File>
<File
RelativePath="..\base_switches.h"
>
</File>
<File
RelativePath="..\basictypes.h"
>
</File>
<File
RelativePath="..\third_party\nss\blapi.h"
>
</File>
<File
RelativePath="..\third_party\nss\blapit.h"
>
</File>
<File
RelativePath="..\clipboard.cc"
>
</File>
<File
RelativePath="..\clipboard.h"
>
</File>
<File
RelativePath="..\clipboard_util.cc"
>
</File>
<File
RelativePath="..\clipboard_util.h"
>
</File>
<File
RelativePath="..\command_line.cc"
>
</File>
<File
RelativePath="..\command_line.h"
>
</File>
<File
RelativePath="..\condition_variable.cc"
>
</File>
<File
RelativePath="..\condition_variable.h"
>
</File>
<File
RelativePath="..\debug_on_start.cc"
>
</File>
<File
RelativePath="..\debug_on_start.h"
>
</File>
<File
RelativePath="..\debug_util.cc"
>
</File>
<File
RelativePath="..\debug_util.h"
>
</File>
<File
RelativePath="..\event_recorder.cc"
>
</File>
<File
RelativePath="..\event_recorder.h"
>
</File>
<File
RelativePath="..\file_util.cc"
>
</File>
<File
RelativePath="..\file_util.h"
>
</File>
<File
RelativePath="..\file_version_info.cc"
>
</File>
<File
RelativePath="..\file_version_info.h"
>
</File>
<File
RelativePath="..\fix_wp64.h"
>
</File>
<File
RelativePath="..\fixed_string.h"
>
</File>
<File
RelativePath="..\histogram.cc"
>
</File>
<File
RelativePath="..\histogram.h"
>
</File>
<File
RelativePath="..\hmac.cc"
>
</File>
<File
RelativePath="..\hmac.h"
>
</File>
<File
RelativePath="..\iat_patch.cc"
>
</File>
<File
RelativePath="..\iat_patch.h"
>
</File>
<File
RelativePath="..\icu_util.cc"
>
</File>
<File
RelativePath="..\icu_util.h"
>
</File>
<File
RelativePath="..\id_map.h"
>
</File>
<File
RelativePath="..\idle_timer.cc"
>
</File>
<File
RelativePath="..\idle_timer.h"
>
</File>
<File
RelativePath="..\image_util.cc"
>
</File>
<File
RelativePath="..\image_util.h"
>
</File>
<File
RelativePath="..\json_reader.cc"
>
</File>
<File
RelativePath="..\json_reader.h"
>
</File>
<File
RelativePath="..\json_writer.cc"
>
</File>
<File
RelativePath="..\json_writer.h"
>
</File>
<File
RelativePath="..\linked_ptr.h"
>
</File>
<File
RelativePath="..\lock.cc"
>
</File>
<File
RelativePath="..\lock.h"
>
</File>
<File
RelativePath="..\lock_impl.h"
>
</File>
<File
RelativePath="..\lock_impl_win.cc"
>
</File>
<File
RelativePath="..\logging.cc"
>
</File>
<File
RelativePath="..\logging.h"
>
</File>
<File
RelativePath="..\md5.cc"
>
</File>
<File
RelativePath="..\md5.h"
>
</File>
<File
RelativePath="..\memory_debug.cc"
>
</File>
<File
RelativePath="..\memory_debug.h"
>
</File>
<File
RelativePath="..\message_loop.cc"
>
</File>
<File
RelativePath="..\message_loop.h"
>
</File>
<File
RelativePath="..\non_thread_safe.cc"
>
</File>
<File
RelativePath="..\non_thread_safe.h"
>
</File>
<File
RelativePath="..\observer_list.h"
>
</File>
<File
RelativePath="..\path_service.cc"
>
</File>
<File
RelativePath="..\path_service.h"
>
</File>
<File
RelativePath="..\pe_image.cc"
>
</File>
<File
RelativePath="..\pe_image.h"
>
</File>
<File
RelativePath="..\pickle.cc"
>
</File>
<File
RelativePath="..\pickle.h"
>
</File>
<File
RelativePath="..\platform_thread.cc"
>
</File>
<File
RelativePath="..\platform_thread.h"
>
</File>
<File
RelativePath="..\port.h"
>
</File>
<File
RelativePath="..\third_party\nspr\prcpucfg.h"
>
</File>
<File
RelativePath="..\third_party\nspr\prcpucfg_win.h"
>
</File>
<File
RelativePath="..\process.cc"
>
</File>
<File
RelativePath="..\process.h"
>
</File>
<File
RelativePath="..\process_util.cc"
>
</File>
<File
RelativePath="..\process_util.h"
>
</File>
<File
RelativePath="..\third_party\nspr\prtime.cc"
>
</File>
<File
RelativePath="..\third_party\nspr\prtime.h"
>
</File>
<File
RelativePath="..\third_party\nspr\prtypes.h"
>
</File>
<File
RelativePath="..\third_party\purify\pure.h"
>
</File>
<File
RelativePath="..\third_party\purify\pure_api.c"
>
</File>
<File
RelativePath="..\ref_counted.h"
>
</File>
<File
RelativePath="..\registry.cc"
>
</File>
<File
RelativePath="..\registry.h"
>
</File>
<File
RelativePath="..\resource_util.cc"
>
</File>
<File
RelativePath="..\resource_util.h"
>
</File>
<File
RelativePath="..\revocable_store.cc"
>
</File>
<File
RelativePath="..\revocable_store.h"
>
</File>
<File
RelativePath="..\scoped_handle.h"
>
</File>
<File
RelativePath="..\scoped_ptr.h"
>
</File>
<File
RelativePath="..\sha2.cc"
>
</File>
<File
RelativePath="..\sha2.h"
>
</File>
<File
RelativePath="..\third_party\nss\sha256.h"
>
</File>
<File
RelativePath="..\third_party\nss\sha512.cc"
>
</File>
<File
RelativePath="..\shared_event.cc"
>
</File>
<File
RelativePath="..\shared_event.h"
>
</File>
<File
RelativePath="..\shared_memory.cc"
>
</File>
<File
RelativePath="..\shared_memory.h"
>
</File>
<File
RelativePath="..\singleton.h"
>
</File>
<File
RelativePath="..\singleton_internal.h"
>
</File>
<File
RelativePath="..\spin_wait.h"
>
</File>
<File
RelativePath="..\stack_container.h"
>
</File>
<File
RelativePath="..\stats_counters.h"
>
</File>
<File
RelativePath="..\stats_table.cc"
>
</File>
<File
RelativePath="..\stats_table.h"
>
</File>
<File
RelativePath="..\string16.h"
>
</File>
<File
RelativePath="..\string_escape.cc"
>
</File>
<File
RelativePath="..\string_escape.h"
>
</File>
<File
RelativePath="..\string_piece.cc"
>
</File>
<File
RelativePath="..\string_piece.h"
>
</File>
<File
RelativePath="..\string_tokenizer.h"
>
</File>
<File
RelativePath="..\string_util.cc"
>
</File>
<File
RelativePath="..\string_util.h"
>
</File>
<File
RelativePath="..\string_util_icu.cc"
>
</File>
<File
RelativePath="..\string_util_win.cc"
>
</File>
<File
RelativePath="..\string_util_win.h"
>
</File>
<File
RelativePath="..\task.h"
>
</File>
<File
RelativePath="..\thread.cc"
>
</File>
<File
RelativePath="..\thread.h"
>
</File>
<File
RelativePath="..\thread_local_storage.h"
>
</File>
<File
RelativePath="..\thread_local_storage_win.cc"
>
</File>
<File
RelativePath="..\time.cc"
>
</File>
<File
RelativePath="..\time.h"
>
</File>
<File
RelativePath="..\time_win.cc"
>
</File>
<File
RelativePath="..\timer.cc"
>
</File>
<File
RelativePath="..\timer.h"
>
</File>
<File
RelativePath="..\tracked.cc"
>
</File>
<File
RelativePath="..\tracked.h"
>
</File>
<File
RelativePath="..\tracked_objects.cc"
>
</File>
<File
RelativePath="..\tracked_objects.h"
>
</File>
<File
RelativePath="..\tuple.h"
>
</File>
<File
RelativePath="..\values.cc"
>
</File>
<File
RelativePath="..\values.h"
>
</File>
<File
RelativePath="..\watchdog.cc"
>
</File>
<File
RelativePath="..\watchdog.h"
>
</File>
<File
RelativePath="..\win_util.cc"
>
</File>
<File
RelativePath="..\win_util.h"
>
</File>
<File
RelativePath="..\windows_message_list.h"
>
</File>
<File
RelativePath="..\wmi_util.cc"
>
</File>
<File
RelativePath="..\wmi_util.h"
>
</File>
<File
RelativePath="..\word_iterator.cc"
>
</File>
<File
RelativePath="..\word_iterator.h"
>
</File>
<File
RelativePath="..\worker_pool.cc"
>
</File>
<File
RelativePath="..\worker_pool.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

8
base/build/base.vsprops Normal file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="base"
InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
>
</VisualStudioPropertySheet>

263
base/build/base_gfx.vcproj Normal file

@ -0,0 +1,263 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="base_gfx"
ProjectGUID="{A508ADD3-CECE-4E0F-8448-2F5E454DF551}"
RootNamespace="base_gfx"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\base_gfx.vsprops;..\..\skia\using_skia.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="4"
InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\base_gfx.vsprops;..\..\skia\using_skia.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\gfx\bitmap_header.cc"
>
</File>
<File
RelativePath="..\gfx\bitmap_header.h"
>
</File>
<File
RelativePath="..\gfx\bitmap_platform_device.cc"
>
</File>
<File
RelativePath="..\gfx\bitmap_platform_device.h"
>
</File>
<File
RelativePath="..\gfx\convolver.cc"
>
</File>
<File
RelativePath="..\gfx\convolver.h"
>
</File>
<File
RelativePath="..\gfx\font_utils.cc"
>
</File>
<File
RelativePath="..\gfx\font_utils.h"
>
</File>
<File
RelativePath="..\gfx\image_operations.cc"
>
</File>
<File
RelativePath="..\gfx\image_operations.h"
>
</File>
<File
RelativePath="..\gfx\native_theme.cc"
>
</File>
<File
RelativePath="..\gfx\native_theme.h"
>
</File>
<File
RelativePath="..\gfx\platform_canvas.cc"
>
</File>
<File
RelativePath="..\gfx\platform_canvas.h"
>
</File>
<File
RelativePath="..\gfx\platform_device.cc"
>
</File>
<File
RelativePath="..\gfx\platform_device.h"
>
</File>
<File
RelativePath="..\gfx\png_decoder.cc"
>
</File>
<File
RelativePath="..\gfx\png_decoder.h"
>
</File>
<File
RelativePath="..\gfx\png_encoder.cc"
>
</File>
<File
RelativePath="..\gfx\png_encoder.h"
>
</File>
<File
RelativePath="..\gfx\point.cc"
>
</File>
<File
RelativePath="..\gfx\point.h"
>
</File>
<File
RelativePath="..\gfx\rect.cc"
>
</File>
<File
RelativePath="..\gfx\rect.h"
>
</File>
<File
RelativePath="..\gfx\size.cc"
>
</File>
<File
RelativePath="..\gfx\size.h"
>
</File>
<File
RelativePath="..\gfx\skia_utils.cc"
>
</File>
<File
RelativePath="..\gfx\skia_utils.h"
>
</File>
<File
RelativePath="..\gfx\uniscribe.cc"
>
</File>
<File
RelativePath="..\gfx\uniscribe.h"
>
</File>
<File
RelativePath="..\gfx\vector_canvas.cc"
>
</File>
<File
RelativePath="..\gfx\vector_canvas.h"
>
</File>
<File
RelativePath="..\gfx\vector_device.cc"
>
</File>
<File
RelativePath="..\gfx\vector_device.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="base_gfx"
InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;..\..\skia\using_skia.vsprops"
>
</VisualStudioPropertySheet>

@ -0,0 +1,370 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="base_unittests"
ProjectGUID="{27A30967-4BBA-48D1-8522-CDE95F7B1CEC}"
RootNamespace="base_unittests"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\base_unittests.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="UNIT_TEST"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="1"
InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\base_unittests.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="UNIT_TEST"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="support"
>
<File
RelativePath="..\check_handler.h"
>
</File>
<File
RelativePath="..\multiprocess_test.h"
>
</File>
<File
RelativePath="..\no_windows2000_unittest.h"
>
</File>
<File
RelativePath="..\run_all_unittests.cc"
>
</File>
<File
RelativePath="..\test_suite.h"
>
</File>
</Filter>
<Filter
Name="base_tests"
>
<File
RelativePath="..\atomic_unittest.cc"
>
</File>
<File
RelativePath="..\check_handler_unittest.cc"
>
</File>
<File
RelativePath="..\clipboard_unittest.cc"
>
</File>
<File
RelativePath="..\command_line_unittest.cc"
>
</File>
<File
RelativePath="..\condition_variable_test.cc"
>
</File>
<File
RelativePath="..\file_util_unittest.cc"
>
</File>
<File
RelativePath="..\file_version_info_unittest.cc"
>
</File>
<File
RelativePath="..\fixed_string_unittest.cc"
>
</File>
<File
RelativePath="..\histogram_test.cc"
>
</File>
<File
RelativePath="..\hmac_unittest.cc"
>
</File>
<File
RelativePath="..\idletimer_unittest.cc"
>
</File>
<File
RelativePath="..\json_reader_unittest.cc"
>
</File>
<File
RelativePath="..\json_writer_unittest.cc"
>
</File>
<File
RelativePath="..\linked_ptr_unittest.cc"
>
</File>
<File
RelativePath="..\message_loop_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\native_theme_unittest.cc"
>
</File>
<File
RelativePath="..\path_service_unittest.cc"
>
</File>
<File
RelativePath="..\pe_image_unittest.cc"
>
</File>
<File
RelativePath="..\pickle_unittest.cc"
>
</File>
<File
RelativePath="..\pr_time_test.cc"
>
</File>
<File
RelativePath="..\process_util_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\rect_unittest.cc"
>
</File>
<File
RelativePath="..\ref_counted_unittest.cc"
>
</File>
<File
RelativePath="..\sha2_unittest.cc"
>
</File>
<File
RelativePath="..\shared_event_unittest.cc"
>
</File>
<File
RelativePath="..\shared_memory_unittest.cc"
>
</File>
<File
RelativePath="..\singleton_unittest.cc"
>
</File>
<File
RelativePath="..\stack_container_unittest.cc"
>
</File>
<File
RelativePath="..\stats_table_unittest.cc"
>
</File>
<File
RelativePath="..\string_escape_unittest.cc"
>
</File>
<File
RelativePath="..\string_piece_unittest.cc"
>
</File>
<File
RelativePath="..\string_tokenizer_unittest.cc"
>
</File>
<File
RelativePath="..\string_util_unittest.cc"
>
</File>
<File
RelativePath="..\thread_local_storage_unittest.cc"
>
</File>
<File
RelativePath="..\thread_unittest.cc"
>
</File>
<File
RelativePath="..\time_unittest.cc"
>
</File>
<File
RelativePath="..\timer_unittest.cc"
>
</File>
<File
RelativePath="..\tracked_objects_test.cc"
>
</File>
<File
RelativePath="..\values_unittest.cc"
>
</File>
<File
RelativePath="..\watchdog_test.cc"
>
</File>
<File
RelativePath="..\win_util_unittest.cc"
>
</File>
<File
RelativePath="..\wmi_util_unittest.cc"
>
</File>
</Filter>
<Filter
Name="gfx_tests"
>
<File
RelativePath="..\gfx\convolver_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\image_operations_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\platform_canvas_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\png_codec_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\uniscribe_unittest.cc"
>
</File>
<File
RelativePath="..\gfx\vector_canvas_unittest.cc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="base_unittests"
InheritedPropertySheets=".\base_gfx.vsprops"
>
</VisualStudioPropertySheet>

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="debug_message"
ProjectGUID="{0E5474AC-5996-4B13-87C0-4AE931EE0815}"
RootNamespace="DebugMessage"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
SubSystem="2"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="1"
InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
SubSystem="2"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\debug_message.cc"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,9 @@
EXPORTS
SingletonInt1
SingletonInt2
SingletonInt3
SingletonInt4
SingletonInt5
SingletonNoLeak
SingletonLeak
GetLeakySingleton

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="singleton_dll_unittest"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="SINGLETON_UNITTEST_EXPORTS"
/>
<Tool
Name="VCLinkerTool"
ModuleDefinitionFile="singleton_dll_unittest.def"
/>
</VisualStudioPropertySheet>

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="singleton_dll_unittest"
ProjectGUID="{E457F2FB-4708-4001-9B1C-275D7BD7F2A8}"
RootNamespace="singleton_unittest"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\singleton_dll_unittest.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\singleton_dll_unittest.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\singleton_dll_unittest.cc"
>
</File>
<File
RelativePath=".\singleton_dll_unittest.def"
>
</File>
<File
RelativePath="..\singleton_dll_unittest.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

112
base/check_handler.h Normal file

@ -0,0 +1,112 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_CHECK_HANDLER_H__
#define BASE_CHECK_HANDLER_H__
#include <windows.h>
#include "base/logging.h"
// This class allows temporary handling of assert firing. When a CHECK()
// or DCHECK() assertion happens it will in turn generate a SEH exception
// which can be can captured using a windows SEH hander __try .. _except
// block. One practical use of this class is for unit tests that make sure
// CHECK conditions are appropriately handled. For example:
//
// TEST(TestGroup, VerifyAssert) {
// CheckAssertHandler expect_exception;
// __try {
// MyClass object; // MyClass dtor will not be called.
// Param some_bad_param;
// object.Method(some_bad_param); // Should triggers a CHECK().
// ADD_FAILURE(); // If we get here the test failed.
// } __except(EXCEPTION_EXECUTE_HANDLER) {
// DWORD ecode = GetExceptionCode();
// EXPECT_EQ(CheckAssertHandler::seh_exception_code(), ecode);
// }
// }
//
// You can put MyClass outside the __try block so its destructor will be
// called which could lead to a crash if the state of the object is
// corrupted by the CHECK you are testing. If that is the case you should
// fix the state of the object inside the __except block.
//
// Since the above code is Windows specific, two helper macros are provided
// that hide the implementation details. Using the macros the code becomes:
//
// TEST(TestGroup, VerifyAssert) {
// CHECK_HANDLER_BEGIN
// MyClass object; // MyClass dtor will not be called.
// Param some_bad_param;
// object.Method(some_bad_param); // Should triggers a CHECK().
// CHECK_HANDLER_END
// }
//
// Depending on the compiler settings you might have issue this pragma arround
// the code that uses this class:
// #pragma warning(disable: 4509)
// Which tells the compiler that is ok that some dtors will not be called.
//
// Create this object on the stack always.Do not create it inside the
// __try block itself or the dtor will never be called. Create only one
// on each scope.
//
// The key detail here is the RaiseException() call which transfers
// program control away from the code that caused the assertion and back
// into the _except block.
class CheckAssertHandler {
public:
// Installs the assert handler. The dtor will remove the handler.
CheckAssertHandler() {
logging::SetLogAssertHandler(&CheckAssertHandler::LogAssertHandler);
}
~CheckAssertHandler() {
logging::SetLogAssertHandler(NULL);
}
static DWORD seh_exception_code() { return 0x1765413; }
private:
static void LogAssertHandler(const std::string&) {
::RaiseException(seh_exception_code(), 0, 0, NULL);
}
};
#define CHECK_HANDLER_BEGIN \
CheckAssertHandler chk_ex_handler; \
__try {
#define CHECK_HANDLER_END \
ADD_FAILURE(); \
} __except(EXCEPTION_EXECUTE_HANDLER) { \
DWORD ecode = GetExceptionCode(); \
EXPECT_EQ(CheckAssertHandler::seh_exception_code(), ecode); \
}
#endif // BASE_CHECK_HANDLER_H__

@ -0,0 +1,72 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/check_handler.h"
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class SimpleTestClass {
public:
SimpleTestClass() {
}
~SimpleTestClass() {
ADD_FAILURE();
}
void ThisMethodAsserts() {
CHECK(false);
ADD_FAILURE();
}
};
void ThisFunctionAsserts() {
CHECK(false);
ADD_FAILURE();
}
} // namespace
#pragma warning(push)
#pragma warning(disable: 4509)
TEST(CheckHandlerTest, TestMacroCheckObj) {
CHECK_HANDLER_BEGIN
SimpleTestClass object;
object.ThisMethodAsserts();
CHECK_HANDLER_END
}
TEST(CheckHandlerTest, TestMacroCheckFunc) {
CHECK_HANDLER_BEGIN
ThisFunctionAsserts();
CHECK_HANDLER_END
}
#pragma warning(pop)

658
base/clipboard.cc Normal file

@ -0,0 +1,658 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Many of these functions are based on those found in
// webkit/port/platform/PasteboardWin.cpp
#include <shlobj.h>
#include <shellapi.h>
#include "base/clipboard.h"
#include "base/clipboard_util.h"
#include "base/logging.h"
#include "base/string_util.h"
namespace {
// A small object to ensure we close the clipboard after opening it.
class ClipboardLock {
public:
ClipboardLock() : we_own_the_lock_(false) { }
~ClipboardLock() {
if (we_own_the_lock_)
Release();
}
bool Acquire(HWND owner) {
// We shouldn't be calling this if we already own the clipbard lock.
DCHECK(!we_own_the_lock_);
// We already have the lock. We don't want to stomp on the other use.
if (we_own_the_lock_)
return false;
const int kMaxAttemptsToOpenClipboard = 5;
// Attempt to acquire the clipboard lock. This may fail if another process
// currently holds the lock. We're willing to try a few times in the hopes
// of acquiring it.
//
// This turns out to be an issue when using remote desktop because the
// rdpclip.exe process likes to read what we've written to the clipboard and
// send it to the RDP client. If we open and close the clipboard in quick
// succession, we might be trying to open it while rdpclip.exe has it open,
// See Bug 815425.
//
// In fact, we believe we'll only spin this loop over remote desktop. In
// normal situations, the user is initiating clipboard operations and there
// shouldn't be lock contention.
for (int attempts = 0; attempts < kMaxAttemptsToOpenClipboard; ++attempts) {
if (::OpenClipboard(owner)) {
we_own_the_lock_ = true;
return we_own_the_lock_;
}
// Having failed, we yeild our timeslice to other processes. ::Yield seems
// to be insufficient here, so we sleep for 5 ms.
if (attempts < (kMaxAttemptsToOpenClipboard - 1))
::Sleep(5);
}
// We failed to acquire the clipboard.
return false;
}
void Release() {
// We should only be calling this if we already own the clipbard lock.
DCHECK(we_own_the_lock_);
// We we don't have the lock, there is nothing to release.
if (!we_own_the_lock_)
return;
::CloseClipboard();
we_own_the_lock_ = false;
}
private:
bool we_own_the_lock_;
};
LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
LRESULT lresult = 0;
switch(message) {
case WM_RENDERFORMAT:
// This message comes when SetClipboardData was sent a null data handle
// and now it's come time to put the data on the clipboard.
// We always set data, so there isn't a need to actually do anything here.
break;
case WM_RENDERALLFORMATS:
// This message comes when SetClipboardData was sent a null data handle
// and now this application is about to quit, so it must put data on
// the clipboard before it exits.
// We always set data, so there isn't a need to actually do anything here.
break;
case WM_DRAWCLIPBOARD:
break;
case WM_DESTROY:
break;
case WM_CHANGECBCHAIN:
break;
default:
lresult = DefWindowProc(hwnd, message, wparam, lparam);
break;
}
return lresult;
}
template <typename charT>
HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) {
HGLOBAL data =
::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT)));
if (data) {
charT* raw_data = static_cast<charT*>(::GlobalLock(data));
memcpy(raw_data, str.data(), str.size() * sizeof(charT));
raw_data[str.size()] = '\0';
::GlobalUnlock(data);
}
return data;
};
} // namespace
Clipboard::Clipboard() {
// make a dummy HWND to be the clipboard's owner
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = ClipboardOwnerWndProc;
wcex.hInstance = GetModuleHandle(NULL);
wcex.lpszClassName = L"ClipboardOwnerWindowClass";
::RegisterClassEx(&wcex);
clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass",
L"ClipboardOwnerWindow",
0, 0, 0, 0, 0,
HWND_MESSAGE,
0, 0, 0);
}
Clipboard::~Clipboard() {
::DestroyWindow(clipboard_owner_);
clipboard_owner_ = NULL;
}
void Clipboard::Clear() const {
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
::EmptyClipboard();
}
void Clipboard::WriteText(const std::wstring& text) const {
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HGLOBAL glob = CreateGlobalData(text);
if (glob && !::SetClipboardData(CF_UNICODETEXT, glob))
::GlobalFree(glob);
}
void Clipboard::WriteHTML(const std::wstring& markup,
const std::string& url) const {
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
std::string html_fragment;
MarkupToHTMLClipboardFormat(markup, url, &html_fragment);
HGLOBAL glob = CreateGlobalData(html_fragment);
if (glob && !::SetClipboardData(ClipboardUtil::GetHtmlFormat()->cfFormat,
glob)) {
::GlobalFree(glob);
}
}
void Clipboard::WriteBookmark(const std::wstring& title,
const std::string& url) const {
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
std::wstring bookmark(title);
bookmark.append(1, L'\n');
bookmark.append(UTF8ToWide(url));
HGLOBAL glob = CreateGlobalData(bookmark);
if (glob && !::SetClipboardData(ClipboardUtil::GetUrlWFormat()->cfFormat,
glob)) {
::GlobalFree(glob);
}
}
void Clipboard::WriteHyperlink(const std::wstring& title,
const std::string& url) const {
// Write as a bookmark.
WriteBookmark(title, url);
// Build the HTML link.
std::wstring link(L"<a href=\"");
link.append(UTF8ToWide(url));
link.append(L"\">");
link.append(title);
link.append(L"</a>");
// Write as an HTML link.
WriteHTML(link, std::string());
}
void Clipboard::WriteWebSmartPaste() const {
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
SetClipboardData(ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat, NULL);
}
void Clipboard::WriteBitmap(const void* pixels, const gfx::Size& size) const {
HDC dc = ::GetDC(NULL);
// This doesn't actually cost us a memcpy when the bitmap comes from the
// renderer as we load it into the bitmap using setPixels which just sets a
// pointer. Someone has to memcpy it into GDI, it might as well be us here.
// TODO(darin): share data in gfx/bitmap_header.cc somehow
BITMAPINFO bm_info = {0};
bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bm_info.bmiHeader.biWidth = size.width();
bm_info.bmiHeader.biHeight = -size.height(); // sets vertical orientation
bm_info.bmiHeader.biPlanes = 1;
bm_info.bmiHeader.biBitCount = 32;
bm_info.bmiHeader.biCompression = BI_RGB;
// ::CreateDIBSection allocates memory for us to copy our bitmap into.
// Unfortunately, we can't write the created bitmap to the clipboard,
// (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
void *bits;
HBITMAP source_hbitmap =
::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
if (bits && source_hbitmap) {
// Copy the bitmap out of shared memory and into GDI
memcpy(bits, pixels, 4 * size.width() * size.height());
// Now we have an HBITMAP, we can write it to the clipboard
WriteBitmapFromHandle(source_hbitmap, size);
}
::DeleteObject(source_hbitmap);
::ReleaseDC(NULL, dc);
}
void Clipboard::WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
const gfx::Size& size) const {
// TODO(darin): share data in gfx/bitmap_header.cc somehow
BITMAPINFO bm_info = {0};
bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bm_info.bmiHeader.biWidth = size.width();
bm_info.bmiHeader.biHeight = -size.height(); // Sets the vertical orientation
bm_info.bmiHeader.biPlanes = 1;
bm_info.bmiHeader.biBitCount = 32;
bm_info.bmiHeader.biCompression = BI_RGB;
HDC dc = ::GetDC(NULL);
// We can create an HBITMAP directly using the shared memory handle, saving
// a memcpy.
HBITMAP source_hbitmap =
::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL, bitmap.handle(), 0);
if (source_hbitmap) {
// Now we can write the HBITMAP to the clipboard
WriteBitmapFromHandle(source_hbitmap, size);
}
::DeleteObject(source_hbitmap);
::ReleaseDC(NULL, dc);
}
void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
const gfx::Size& size) const {
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
// We would like to just call ::SetClipboardData on the source_hbitmap,
// but that bitmap might not be of a sort we can write to the clipboard.
// For this reason, we create a new bitmap, copy the bits over, and then
// write that to the clipboard.
HDC dc = ::GetDC(NULL);
HDC compatible_dc = ::CreateCompatibleDC(NULL);
HDC source_dc = ::CreateCompatibleDC(NULL);
// This is the HBITMAP we will eventually write to the clipboard
HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
if (!hbitmap) {
// Failed to create the bitmap
::DeleteDC(compatible_dc);
::DeleteDC(source_dc);
::ReleaseDC(NULL, dc);
return;
}
HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
// Now we need to blend it into an HBITMAP we can place on the clipboard
BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
::AlphaBlend(compatible_dc, 0, 0, size.width(), size.height(),
source_dc, 0, 0, size.width(), size.height(), bf);
// Clean up all the handles we just opened
::SelectObject(compatible_dc, old_hbitmap);
::SelectObject(source_dc, old_source);
::DeleteObject(old_hbitmap);
::DeleteObject(old_source);
::DeleteDC(compatible_dc);
::DeleteDC(source_dc);
::ReleaseDC(NULL, dc);
// Actually write the bitmap to the clipboard
::SetClipboardData(CF_BITMAP, hbitmap);
}
// Write a file or set of files to the clipboard in HDROP format. When the user
// invokes a paste command (in a Windows explorer shell, for example), the files
// will be copied to the paste location.
void Clipboard::WriteFile(const std::wstring& file) const {
std::vector<std::wstring> files;
files.push_back(file);
WriteFiles(files);
}
void Clipboard::WriteFiles(const std::vector<std::wstring>& files) const {
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
// Calculate the amount of space we'll need store the strings: require
// NULL terminator between strings, and double null terminator at the end.
size_t bytes = sizeof(DROPFILES);
for (size_t i = 0; i < files.size(); ++i)
bytes += (files[i].length() + 1) * sizeof(wchar_t);
bytes += sizeof(wchar_t);
HANDLE hdata = ::GlobalAlloc(GMEM_MOVEABLE, bytes);
if (!hdata)
return;
DROPFILES* drop_files = static_cast<DROPFILES*>(::GlobalLock(hdata));
drop_files->pFiles = sizeof(DROPFILES);
drop_files->fWide = TRUE;
BYTE* data = reinterpret_cast<BYTE*>(drop_files) + sizeof(DROPFILES);
// Copy the strings stored in 'files' with proper NULL separation.
wchar_t* data_pos = reinterpret_cast<wchar_t*>(data);
for (size_t i = 0; i < files.size(); ++i) {
size_t offset = files[i].length() + 1;
memcpy(data_pos, files[i].c_str(), offset * sizeof(wchar_t));
data_pos += offset;
}
data_pos[0] = L'\0'; // Double NULL termination after the last string.
::GlobalUnlock(hdata);
if (!::SetClipboardData(CF_HDROP, hdata))
::GlobalFree(hdata);
}
bool Clipboard::IsFormatAvailable(unsigned int format) const {
return ::IsClipboardFormatAvailable(format) != FALSE;
}
void Clipboard::ReadText(std::wstring* result) const {
if (!result) {
NOTREACHED();
return;
}
result->clear();
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
if (!data)
return;
result->assign(static_cast<const wchar_t*>(::GlobalLock(data)));
::GlobalUnlock(data);
}
void Clipboard::ReadAsciiText(std::string* result) const {
if (!result) {
NOTREACHED();
return;
}
result->clear();
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HANDLE data = ::GetClipboardData(CF_TEXT);
if (!data)
return;
result->assign(static_cast<const char*>(::GlobalLock(data)));
::GlobalUnlock(data);
}
void Clipboard::ReadHTML(std::wstring* markup, std::string* src_url) const {
if (markup)
markup->clear();
if (src_url)
src_url->clear();
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HANDLE data = ::GetClipboardData(ClipboardUtil::GetHtmlFormat()->cfFormat);
if (!data)
return;
std::string html_fragment(static_cast<const char*>(::GlobalLock(data)));
::GlobalUnlock(data);
ParseHTMLClipboardFormat(html_fragment, markup, src_url);
}
void Clipboard::ReadBookmark(std::wstring* title, std::string* url) const {
if (title)
title->clear();
if (url)
url->clear();
// Acquire the clipboard.
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HANDLE data = ::GetClipboardData(ClipboardUtil::GetUrlWFormat()->cfFormat);
if (!data)
return;
std::wstring bookmark(static_cast<const wchar_t*>(::GlobalLock(data)));
::GlobalUnlock(data);
ParseBookmarkClipboardFormat(bookmark, title, url);
}
// Read a file in HDROP format from the clipboard.
void Clipboard::ReadFile(std::wstring* file) const {
if (!file) {
NOTREACHED();
return;
}
file->clear();
std::vector<std::wstring> files;
ReadFiles(&files);
// Take the first file, if available.
if (!files.empty())
file->assign(files[0]);
}
// Read a set of files in HDROP format from the clipboard.
void Clipboard::ReadFiles(std::vector<std::wstring>* files) const {
if (!files) {
NOTREACHED();
return;
}
files->clear();
ClipboardLock lock;
if (!lock.Acquire(clipboard_owner_))
return;
HDROP drop = static_cast<HDROP>(::GetClipboardData(CF_HDROP));
if (!drop)
return;
// Count of files in the HDROP.
int count = ::DragQueryFile(drop, 0xffffffff, NULL, 0);
if (count) {
for (int i = 0; i < count; ++i) {
int size = ::DragQueryFile(drop, i, NULL, 0) + 1;
std::wstring file;
::DragQueryFile(drop, i, WriteInto(&file, size), size);
files->push_back(file);
}
}
}
// static
void Clipboard::MarkupToHTMLClipboardFormat(const std::wstring& markup,
const std::string& src_url,
std::string* html_fragment) {
DCHECK(html_fragment);
// Documentation for the CF_HTML format is available at
// http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp
if (markup.empty()) {
html_fragment->clear();
return;
}
std::string markup_utf8 = WideToUTF8(markup);
html_fragment->assign("Version:0.9");
std::string start_html("\nStartHTML:");
std::string end_html("\nEndHTML:");
std::string start_fragment("\nStartFragment:");
std::string end_fragment("\nEndFragment:");
std::string source_url("\nSourceURL:");
bool has_source_url = !src_url.empty() &&
!StartsWithASCII(src_url, "about:", false);
if (has_source_url)
source_url.append(src_url);
std::string start_markup("\n<HTML>\n<BODY>\n<!--StartFragment-->\n");
std::string end_markup("\n<!--EndFragment-->\n</BODY>\n</HTML>");
// calculate offsets
const size_t kMaxDigits = 10; // number of digits in UINT_MAX in base 10
size_t start_html_offset, start_fragment_offset;
size_t end_fragment_offset, end_html_offset;
start_html_offset = html_fragment->length() +
start_html.length() + end_html.length() +
start_fragment.length() + end_fragment.length() +
(has_source_url ? source_url.length() : 0) +
(4*kMaxDigits);
start_fragment_offset = start_html_offset + start_markup.length();
end_fragment_offset = start_fragment_offset + markup_utf8.length();
end_html_offset = end_fragment_offset + end_markup.length();
// fill in needed data
start_html.append(StringPrintf("%010u", start_html_offset));
end_html.append(StringPrintf("%010u", end_html_offset));
start_fragment.append(StringPrintf("%010u", start_fragment_offset));
end_fragment.append(StringPrintf("%010u", end_fragment_offset));
start_markup.append(markup_utf8);
// create full html_fragment string from the fragments
html_fragment->append(start_html);
html_fragment->append(end_html);
html_fragment->append(start_fragment);
html_fragment->append(end_fragment);
if (has_source_url)
html_fragment->append(source_url);
html_fragment->append(start_markup);
html_fragment->append(end_markup);
}
// static
void Clipboard::ParseHTMLClipboardFormat(const std::string& html_frag,
std::wstring* markup,
std::string* src_url) {
if (src_url) {
// Obtain SourceURL, if present
std::string src_url_str("SourceURL:");
size_t line_start = html_frag.find(src_url_str, 0);
if (line_start != std::string::npos) {
size_t src_start = line_start+src_url_str.length();
size_t src_end = html_frag.find("\n", line_start);
if (src_end != std::string::npos)
*src_url = html_frag.substr(src_start, src_end - src_start);
}
}
if (markup) {
// Find the markup between "<!--StartFragment -->" and
// "<!--EndFragment -->", accounting for browser quirks
size_t markup_start = html_frag.find('<', 0);
size_t tag_start = html_frag.find("StartFragment", markup_start);
size_t frag_start = html_frag.find('>', tag_start) + 1;
// Here we do something slightly differently than WebKit. Webkit does a
// forward find for EndFragment, but that seems to be a bug if the html
// fragment actually includes the string "EndFragment"
size_t tag_end = html_frag.rfind("EndFragment", std::string::npos);
size_t frag_end = html_frag.rfind('<', tag_end);
TrimWhitespace(UTF8ToWide(html_frag.substr(frag_start,
frag_end - frag_start)),
TRIM_ALL, markup);
}
}
// static
void Clipboard::ParseBookmarkClipboardFormat(const std::wstring& bookmark,
std::wstring* title,
std::string* url) {
const wchar_t* const kDelim = L"\r\n";
const size_t title_end = bookmark.find_first_of(kDelim);
if (title)
title->assign(bookmark.substr(0, title_end));
if (url) {
const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
if (url_start != std::wstring::npos)
*url = WideToUTF8(bookmark.substr(url_start, std::wstring::npos));
}
}

126
base/clipboard.h Normal file

@ -0,0 +1,126 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_CLIPBOARD_H__
#define BASE_CLIPBOARD_H__
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/gfx/size.h"
#include "base/shared_memory.h"
class Clipboard {
public:
Clipboard();
~Clipboard();
// Clears the clipboard. It is usually a good idea to clear the clipboard
// before writing content to the clipboard.
void Clear() const;
// Adds UNICODE and ASCII text to the clipboard.
void WriteText(const std::wstring& text) const;
// Adds HTML to the clipboard. The url parameter is optional, but especially
// useful if the HTML fragment contains relative links
void WriteHTML(const std::wstring& markup, const std::string& src_url) const;
// Adds a bookmark to the clipboard
void WriteBookmark(const std::wstring& title, const std::string& url) const;
// Adds both a bookmark and an HTML hyperlink to the clipboard. It is a
// convenience wrapper around WriteBookmark and WriteHTML.
void WriteHyperlink(const std::wstring& title, const std::string& url) const;
// Adds a bitmap to the clipboard
// This is the slowest way to copy a bitmap to the clipboard as we must first
// memcpy the pixels into GDI and the blit the bitmap to the clipboard.
// Pixel format is assumed to be 32-bit BI_RGB.
void WriteBitmap(const void* pixels, const gfx::Size& size) const;
// Adds a bitmap to the clipboard
// This function requires read and write access to the bitmap, but does not
// actually modify the shared memory region.
// Pixel format is assumed to be 32-bit BI_RGB.
void WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
const gfx::Size& size) const;
// Adds a bitmap to the clipboard
// This is the fastest way to copy a bitmap to the clipboard. The HBITMAP
// may either be device-dependent or device-independent.
void WriteBitmapFromHandle(HBITMAP hbitmap, const gfx::Size& size) const;
// Used by WebKit to determine whether WebKit wrote the clipboard last
void WriteWebSmartPaste() const;
// Adds a file or group of files to the clipboard.
void WriteFile(const std::wstring& file) const;
void WriteFiles(const std::vector<std::wstring>& files) const;
// Tests whether the clipboard contains a certain format
bool IsFormatAvailable(unsigned int format) const;
// Reads UNICODE text from the clipboard, if available.
void ReadText(std::wstring* result) const;
// Reads ASCII text from the clipboard, if available.
void ReadAsciiText(std::string* result) const;
// Reads HTML from the clipboard, if available.
void ReadHTML(std::wstring* markup, std::string* src_url) const;
// Reads a bookmark from the clipboard, if available.
void ReadBookmark(std::wstring* title, std::string* url) const;
// Reads a file or group of files from the clipboard, if available, into the
// out paramter.
void ReadFile(std::wstring* file) const;
void ReadFiles(std::vector<std::wstring>* files) const;
private:
static void MarkupToHTMLClipboardFormat(const std::wstring& markup,
const std::string& src_url,
std::string* html_fragment);
static void ParseHTMLClipboardFormat(const std::string& html_fragment,
std::wstring* markup,
std::string* src_url);
static void ParseBookmarkClipboardFormat(const std::wstring& bookmark,
std::wstring* title,
std::string* url);
HWND clipboard_owner_;
DISALLOW_EVIL_CONSTRUCTORS(Clipboard);
};
#endif // BASE_CLIPBOARD_H__

211
base/clipboard_unittest.cc Normal file

@ -0,0 +1,211 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include "base/basictypes.h"
#include "base/clipboard.h"
#include "base/clipboard_util.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class ClipboardTest : public testing::Test {
};
}
TEST(ClipboardTest, ClearTest) {
Clipboard clipboard;
clipboard.Clear();
EXPECT_EQ(false, clipboard.IsFormatAvailable(CF_TEXT));
EXPECT_EQ(false, clipboard.IsFormatAvailable(
ClipboardUtil::GetHtmlFormat()->cfFormat));
}
TEST(ClipboardTest, TextTest) {
Clipboard clipboard;
std::wstring text(L"This is a wstring!#$"), text_result;
std::string ascii_text;
clipboard.Clear();
clipboard.WriteText(text);
EXPECT_EQ(true, clipboard.IsFormatAvailable(CF_UNICODETEXT));
EXPECT_EQ(true, clipboard.IsFormatAvailable(CF_TEXT));
clipboard.ReadText(&text_result);
EXPECT_EQ(text, text_result);
clipboard.ReadAsciiText(&ascii_text);
EXPECT_EQ(WideToUTF8(text), ascii_text);
}
TEST(ClipboardTest, HTMLTest) {
Clipboard clipboard;
std::wstring markup(L"<strong>Hi!</string>"), markup_result;
std::string url("http://www.example.com/"), url_result;
clipboard.Clear();
clipboard.WriteHTML(markup, url);
EXPECT_EQ(true, clipboard.IsFormatAvailable(
ClipboardUtil::GetHtmlFormat()->cfFormat));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
EXPECT_EQ(url, url_result);
}
TEST(ClipboardTest, TrickyHTMLTest) {
Clipboard clipboard;
std::wstring markup(L"<em>Bye!<!--EndFragment --></em>"), markup_result;
std::string url, url_result;
clipboard.Clear();
clipboard.WriteHTML(markup, url);
EXPECT_EQ(true, clipboard.IsFormatAvailable(
ClipboardUtil::GetHtmlFormat()->cfFormat));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
EXPECT_EQ(url, url_result);
}
TEST(ClipboardTest, BookmarkTest) {
Clipboard clipboard;
std::wstring title(L"The Example Company"), title_result;
std::string url("http://www.example.com/"), url_result;
clipboard.Clear();
clipboard.WriteBookmark(title, url);
EXPECT_EQ(true,
clipboard.IsFormatAvailable(ClipboardUtil::GetUrlWFormat()->cfFormat));
clipboard.ReadBookmark(&title_result, &url_result);
EXPECT_EQ(title, title_result);
EXPECT_EQ(url, url_result);
}
TEST(ClipboardTest, HyperlinkTest) {
Clipboard clipboard;
std::wstring title(L"The Example Company"), title_result;
std::string url("http://www.example.com/"), url_result;
std::wstring html(L"<a href=\"http://www.example.com/\">"
L"The Example Company</a>"), html_result;
clipboard.Clear();
clipboard.WriteHyperlink(title, url);
EXPECT_EQ(true,
clipboard.IsFormatAvailable(ClipboardUtil::GetUrlWFormat()->cfFormat));
EXPECT_EQ(true,
clipboard.IsFormatAvailable(ClipboardUtil::GetHtmlFormat()->cfFormat));
clipboard.ReadBookmark(&title_result, &url_result);
EXPECT_EQ(title, title_result);
EXPECT_EQ(url, url_result);
clipboard.ReadHTML(&html_result, &url_result);
EXPECT_EQ(html, html_result);
//XXX EXPECT_FALSE(url_result.is_valid());
}
TEST(ClipboardTest, MultiFormatTest) {
Clipboard clipboard;
std::wstring text(L"Hi!"), text_result;
std::wstring markup(L"<strong>Hi!</string>"), markup_result;
std::string url("http://www.example.com/"), url_result;
std::string ascii_text;
clipboard.Clear();
clipboard.WriteHTML(markup, url);
clipboard.WriteText(text);
EXPECT_EQ(true,
clipboard.IsFormatAvailable(ClipboardUtil::GetHtmlFormat()->cfFormat));
EXPECT_EQ(true, clipboard.IsFormatAvailable(CF_UNICODETEXT));
EXPECT_EQ(true, clipboard.IsFormatAvailable(CF_TEXT));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
EXPECT_EQ(url, url_result);
clipboard.ReadText(&text_result);
EXPECT_EQ(text, text_result);
clipboard.ReadAsciiText(&ascii_text);
EXPECT_EQ(WideToUTF8(text), ascii_text);
}
TEST(ClipboardTest, WebSmartPasteTest) {
Clipboard clipboard;
clipboard.Clear();
clipboard.WriteWebSmartPaste();
EXPECT_EQ(true, clipboard.IsFormatAvailable(
ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat));
}
TEST(ClipboardTest, BitmapTest) {
unsigned int fake_bitmap[] = {
0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89,
0x78FD46AE, 0x87C64F5A, 0x36EDC5AF, 0x4378F568,
0x91E9F63A, 0xC31EA14F, 0x69AB32DF, 0x643A3FD1,
};
Clipboard clipboard;
clipboard.Clear();
clipboard.WriteBitmap(fake_bitmap, gfx::Size(3, 4));
EXPECT_EQ(true, clipboard.IsFormatAvailable(CF_BITMAP));
}
// Files for this test don't actually need to exist on the file system, just
// don't try to use a non-existent file you've retrieved from the clipboard.
TEST(ClipboardTest, FileTest) {
Clipboard clipboard;
clipboard.Clear();
std::wstring file = L"C:\\Downloads\\My Downloads\\A Special File.txt";
clipboard.WriteFile(file);
std::wstring out_file;
clipboard.ReadFile(&out_file);
EXPECT_EQ(file, out_file);
}
TEST(ClipboardTest, MultipleFilesTest) {
Clipboard clipboard;
clipboard.Clear();
std::vector<std::wstring> files;
files.push_back(L"C:\\Downloads\\My Downloads\\File 1.exe");
files.push_back(L"C:\\Downloads\\My Downloads\\File 2.pdf");
files.push_back(L"C:\\Downloads\\My Downloads\\File 3.doc");
clipboard.WriteFiles(files);
std::vector<std::wstring> out_files;
clipboard.ReadFiles(&out_files);
EXPECT_EQ(files.size(), out_files.size());
for (size_t i = 0; i < out_files.size(); ++i)
EXPECT_EQ(files[i], out_files[i]);
}

400
base/clipboard_util.cc Normal file

@ -0,0 +1,400 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/clipboard_util.h"
#include <shellapi.h>
#include <shlwapi.h>
#include <wininet.h>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/string_util.h"
namespace {
bool GetUrlFromHDrop(IDataObject* data_object, std::wstring* url,
std::wstring* title) {
DCHECK(data_object && url && title);
STGMEDIUM medium;
if (FAILED(data_object->GetData(ClipboardUtil::GetCFHDropFormat(), &medium)))
return false;
HDROP hdrop = static_cast<HDROP>(GlobalLock(medium.hGlobal));
if (!hdrop)
return false;
bool success = false;
wchar_t filename[MAX_PATH];
if (DragQueryFileW(hdrop, 0, filename, arraysize(filename))) {
wchar_t url_buffer[INTERNET_MAX_URL_LENGTH];
if (0 == _wcsicmp(PathFindExtensionW(filename), L".url") &&
GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, url_buffer,
arraysize(url_buffer), filename)) {
*url = url_buffer;
PathRemoveExtension(filename);
title->assign(PathFindFileName(filename));
success = true;
}
}
DragFinish(hdrop);
GlobalUnlock(medium.hGlobal);
// We don't need to call ReleaseStgMedium here because as far as I can tell,
// DragFinish frees the hGlobal for us.
return success;
}
bool SplitUrlAndTitle(const std::wstring& str, std::wstring* url,
std::wstring* title) {
DCHECK(url && title);
size_t newline_pos = str.find('\n');
bool success = false;
if (newline_pos != std::string::npos) {
*url = str.substr(0, newline_pos);
title->assign(str.substr(newline_pos + 1));
success = true;
} else {
*url = str;
title->assign(str);
success = true;
}
return success;
}
} // namespace
FORMATETC* ClipboardUtil::GetUrlFormat() {
static UINT cf = RegisterClipboardFormat(CFSTR_INETURLA);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetUrlWFormat() {
static UINT cf = RegisterClipboardFormat(CFSTR_INETURLW);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetMozUrlFormat() {
// The format is "URL\nTitle"
static UINT cf = RegisterClipboardFormat(L"text/x-moz-url");
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetPlainTextFormat() {
// We don't need to register this format since it's a built in format.
static FORMATETC format = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetPlainTextWFormat() {
// We don't need to register this format since it's a built in format.
static FORMATETC format = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1,
TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetFilenameWFormat() {
static UINT cf = RegisterClipboardFormat(CFSTR_FILENAMEW);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetFilenameFormat()
{
static UINT cf = RegisterClipboardFormat(CFSTR_FILENAMEA);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetHtmlFormat() {
static UINT cf = RegisterClipboardFormat(L"HTML Format");
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetTextHtmlFormat() {
static UINT cf = RegisterClipboardFormat(L"text/html");
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetCFHDropFormat() {
// We don't need to register this format since it's a built in format.
static FORMATETC format = {CF_HDROP, 0, DVASPECT_CONTENT, -1,
TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetFileDescriptorFormat() {
static UINT cf = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetFileContentFormatZero() {
static UINT cf = RegisterClipboardFormat(CFSTR_FILECONTENTS);
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, 0, TYMED_HGLOBAL};
return &format;
}
FORMATETC* ClipboardUtil::GetWebKitSmartPasteFormat() {
static UINT cf = RegisterClipboardFormat(L"WebKit Smart Paste Format");
static FORMATETC format = {cf, 0, DVASPECT_CONTENT, 0, TYMED_HGLOBAL};
return &format;
}
bool ClipboardUtil::HasUrl(IDataObject* data_object) {
DCHECK(data_object);
return SUCCEEDED(data_object->QueryGetData(GetMozUrlFormat())) ||
SUCCEEDED(data_object->QueryGetData(GetUrlWFormat())) ||
SUCCEEDED(data_object->QueryGetData(GetUrlFormat())) ||
SUCCEEDED(data_object->QueryGetData(GetFilenameWFormat())) ||
SUCCEEDED(data_object->QueryGetData(GetFilenameFormat()));
}
bool ClipboardUtil::HasFilenames(IDataObject* data_object) {
DCHECK(data_object);
return SUCCEEDED(data_object->QueryGetData(GetCFHDropFormat()));
}
bool ClipboardUtil::HasPlainText(IDataObject* data_object) {
DCHECK(data_object);
return SUCCEEDED(data_object->QueryGetData(GetPlainTextWFormat())) ||
SUCCEEDED(data_object->QueryGetData(GetPlainTextFormat()));
}
bool ClipboardUtil::GetUrl(IDataObject* data_object,
std::wstring* url, std::wstring* title) {
DCHECK(data_object && url && title);
if (!HasUrl(data_object))
return false;
// Try to extract a URL from |data_object| in a variety of formats.
STGMEDIUM store;
if (GetUrlFromHDrop(data_object, url, title)) {
return true;
}
if (SUCCEEDED(data_object->GetData(GetMozUrlFormat(), &store)) ||
SUCCEEDED(data_object->GetData(GetUrlWFormat(), &store))) {
// Mozilla URL format or unicode URL
ScopedHGlobal<wchar_t> data(store.hGlobal);
bool success = SplitUrlAndTitle(data.get(), url, title);
ReleaseStgMedium(&store);
if (success)
return true;
}
if (SUCCEEDED(data_object->GetData(GetUrlFormat(), &store))) {
// URL using ascii
ScopedHGlobal<char> data(store.hGlobal);
bool success = SplitUrlAndTitle(UTF8ToWide(data.get()), url, title);
ReleaseStgMedium(&store);
if (success)
return true;
}
if (SUCCEEDED(data_object->GetData(GetFilenameWFormat(), &store))) {
// filename using unicode
ScopedHGlobal<wchar_t> data(store.hGlobal);
bool success = false;
if (data.get() && data.get()[0] && (PathFileExists(data.get()) ||
PathIsUNC(data.get()))) {
wchar_t file_url[INTERNET_MAX_URL_LENGTH];
DWORD file_url_len = sizeof(file_url) / sizeof(file_url[0]);
if (SUCCEEDED(::UrlCreateFromPathW(data.get(), file_url, &file_url_len,
0))) {
*url = file_url;
title->assign(file_url);
success = true;
}
}
ReleaseStgMedium(&store);
if (success)
return true;
}
if (SUCCEEDED(data_object->GetData(GetFilenameFormat(), &store))) {
// filename using ascii
ScopedHGlobal<char> data(store.hGlobal);
bool success = false;
if (data.get() && data.get()[0] && (PathFileExistsA(data.get()) ||
PathIsUNCA(data.get()))) {
char file_url[INTERNET_MAX_URL_LENGTH];
DWORD file_url_len = sizeof(file_url) / sizeof(file_url[0]);
if (SUCCEEDED(::UrlCreateFromPathA(data.get(), file_url, &file_url_len, 0))) {
*url = UTF8ToWide(file_url);
title->assign(*url);
success = true;
}
}
ReleaseStgMedium(&store);
if (success)
return true;
}
return false;
}
bool ClipboardUtil::GetFilenames(IDataObject* data_object,
std::vector<std::wstring>* filenames) {
DCHECK(data_object && filenames);
if (!HasFilenames(data_object))
return false;
STGMEDIUM medium;
if (FAILED(data_object->GetData(GetCFHDropFormat(), &medium)))
return false;
HDROP hdrop = static_cast<HDROP>(GlobalLock(medium.hGlobal));
if (!hdrop)
return false;
const int kMaxFilenameLen = 4096;
const unsigned num_files = DragQueryFileW(hdrop, 0xffffffff, 0, 0);
for (unsigned int i = 0; i < num_files; ++i) {
wchar_t filename[kMaxFilenameLen];
if (!DragQueryFileW(hdrop, i, filename, kMaxFilenameLen))
continue;
filenames->push_back(filename);
}
DragFinish(hdrop);
GlobalUnlock(medium.hGlobal);
// We don't need to call ReleaseStgMedium here because as far as I can tell,
// DragFinish frees the hGlobal for us.
return true;
}
bool ClipboardUtil::GetPlainText(IDataObject* data_object,
std::wstring* plain_text) {
DCHECK(data_object && plain_text);
if (!HasPlainText(data_object))
return false;
STGMEDIUM store;
bool success = false;
if (SUCCEEDED(data_object->GetData(GetPlainTextWFormat(), &store))) {
// Unicode text
ScopedHGlobal<wchar_t> data(store.hGlobal);
plain_text->assign(data.get());
ReleaseStgMedium(&store);
success = true;
} else if (SUCCEEDED(data_object->GetData(GetPlainTextFormat(), &store))) {
// ascii text
ScopedHGlobal<char> data(store.hGlobal);
plain_text->assign(UTF8ToWide(data.get()));
ReleaseStgMedium(&store);
success = true;
} else {
//If a file is dropped on the window, it does not provide either of the
//plain text formats, so here we try to forcibly get a url.
std::wstring title;
success = GetUrl(data_object, plain_text, &title);
}
return success;
}
bool ClipboardUtil::GetCFHtml(IDataObject* data_object,
std::wstring* cf_html) {
DCHECK(data_object && cf_html);
if (FAILED(data_object->QueryGetData(GetHtmlFormat())))
return false;
STGMEDIUM store;
if (FAILED(data_object->GetData(GetHtmlFormat(), &store)))
return false;
// MS CF html
ScopedHGlobal<char> data(store.hGlobal);
cf_html->assign(UTF8ToWide(std::string(data.get(), data.Size())));
ReleaseStgMedium(&store);
return true;
}
bool ClipboardUtil::GetTextHtml(IDataObject* data_object,
std::wstring* text_html) {
DCHECK(data_object && text_html);
if (FAILED(data_object->QueryGetData(GetTextHtmlFormat())))
return false;
STGMEDIUM store;
if (FAILED(data_object->GetData(GetTextHtmlFormat(), &store)))
return false;
// raw html
ScopedHGlobal<wchar_t> data(store.hGlobal);
text_html->assign(data.get());
ReleaseStgMedium(&store);
return true;
}
bool ClipboardUtil::GetFileContents(IDataObject* data_object,
std::wstring* filename, std::string* file_contents) {
DCHECK(data_object && filename && file_contents);
bool has_data =
SUCCEEDED(data_object->QueryGetData(GetFileContentFormatZero())) ||
SUCCEEDED(data_object->QueryGetData(GetFileDescriptorFormat()));
if (!has_data)
return false;
STGMEDIUM content;
// The call to GetData can be very slow depending on what is in
// |data_object|.
if (SUCCEEDED(data_object->GetData(GetFileContentFormatZero(), &content))) {
if (TYMED_HGLOBAL == content.tymed) {
ScopedHGlobal<char> data(content.hGlobal);
// The size includes the trailing NULL byte. We don't want it.
file_contents->assign(data.get(), data.Size() - 1);
}
ReleaseStgMedium(&content);
}
STGMEDIUM description;
if (SUCCEEDED(data_object->GetData(GetFileDescriptorFormat(),
&description))) {
ScopedHGlobal<FILEGROUPDESCRIPTOR> fgd(description.hGlobal);
// We expect there to be at least one file in here.
DCHECK(fgd->cItems >= 1);
filename->assign(fgd->fgd[0].cFileName);
ReleaseStgMedium(&description);
}
return true;
}

76
base/clipboard_util.h Normal file

@ -0,0 +1,76 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Some helper functions for working with the clipboard and IDataObjects.
#include <shlobj.h>
#include <string>
#include <vector>
class ClipboardUtil {
public:
/////////////////////////////////////////////////////////////////////////////
// Clipboard formats.
static FORMATETC* GetUrlFormat();
static FORMATETC* GetUrlWFormat();
static FORMATETC* GetMozUrlFormat();
static FORMATETC* GetPlainTextFormat();
static FORMATETC* GetPlainTextWFormat();
static FORMATETC* GetFilenameFormat();
static FORMATETC* GetFilenameWFormat();
// MS HTML Format
static FORMATETC* GetHtmlFormat();
// Firefox text/html
static FORMATETC* GetTextHtmlFormat();
static FORMATETC* GetCFHDropFormat();
static FORMATETC* GetFileDescriptorFormat();
static FORMATETC* GetFileContentFormatZero();
static FORMATETC* GetWebKitSmartPasteFormat();
/////////////////////////////////////////////////////////////////////////////
// These methods check to see if |data_object| has the requested type.
// Returns true if it does.
static bool HasUrl(IDataObject* data_object);
static bool HasFilenames(IDataObject* data_object);
static bool HasPlainText(IDataObject* data_object);
/////////////////////////////////////////////////////////////////////////////
// Helper methods to extract information from an IDataObject. These methods
// return true if the requested data type is found in |data_object|.
static bool GetUrl(IDataObject* data_object,
std::wstring* url, std::wstring* title);
static bool GetFilenames(IDataObject* data_object,
std::vector<std::wstring>* filenames);
static bool GetPlainText(IDataObject* data_object, std::wstring* plain_text);
static bool GetCFHtml(IDataObject* data_object, std::wstring* cf_html);
static bool GetTextHtml(IDataObject* data_object, std::wstring* text_html);
static bool GetFileContents(IDataObject* data_object,
std::wstring* filename,
std::string* file_contents);
};

246
base/command_line.cc Normal file

@ -0,0 +1,246 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windows.h>
#include <shellapi.h>
#include <algorithm>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"
using namespace std;
// Since we use a lazy match, make sure that longer versions (like L"--")
// are listed before shorter versions (like L"-") of similar prefixes.
const wchar_t* const CommandLine::kSwitchPrefixes[] = {L"--", L"-", L"/"};
const wchar_t CommandLine::kSwitchValueSeparator[] = L"=";
static void Lowercase(wstring* parameter) {
transform(parameter->begin(), parameter->end(), parameter->begin(), tolower);
}
// CommandLine::Data
//
// This object holds the parsed data for a command line. We hold this in a
// separate object from |CommandLine| so that we can share the parsed data
// across multiple |CommandLine| objects. When we share |Data|, we might be
// accessing this object on multiple threads. To ensure thread safety, the
// public interface of this object is const only.
//
// Do NOT add any non-const methods to this object. You have been warned.
class CommandLine::Data {
public:
Data() {
Init(GetCommandLineW());
}
Data(const wstring& command_line) {
Init(command_line);
}
const std::wstring& command_line_string() const {
return command_line_string_;
}
const std::wstring& program() const {
return program_;
}
const std::map<std::wstring, std::wstring>& switches() const {
return switches_;
}
const std::vector<std::wstring>& loose_values() const {
return loose_values_;
}
private:
// Returns true if parameter_string represents a switch. If true,
// switch_string and switch_value are set. (If false, both are
// set to the empty string.)
static bool IsSwitch(const wstring& parameter_string,
wstring* switch_string,
wstring* switch_value) {
*switch_string = L"";
*switch_value = L"";
for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
std::wstring prefix(kSwitchPrefixes[i]);
if (parameter_string.find(prefix) != 0) // check prefix
continue;
const size_t switch_start = prefix.length();
const size_t equals_position = parameter_string.find(
kSwitchValueSeparator, switch_start);
if (equals_position == wstring::npos) {
*switch_string = parameter_string.substr(switch_start);
} else {
*switch_string = parameter_string.substr(
switch_start, equals_position - switch_start);
*switch_value = parameter_string.substr(equals_position + 1);
}
Lowercase(switch_string);
return true;
}
return false;
}
// Does the actual parsing of the command line.
void Init(const std::wstring& command_line) {
TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
if (command_line_string_.empty())
return;
int num_args = 0;
wchar_t** args = NULL;
args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
// Populate program_ with the trimmed version of the first arg.
TrimWhitespace(args[0], TRIM_ALL, &program_);
for (int i = 1; i < num_args; ++i) {
wstring arg;
TrimWhitespace(args[i], TRIM_ALL, &arg);
wstring switch_string;
wstring switch_value;
if (IsSwitch(arg, &switch_string, &switch_value)) {
switches_[switch_string] = switch_value;
} else {
loose_values_.push_back(arg);
}
}
if (args)
LocalFree(args);
}
std::wstring command_line_string_;
std::wstring program_;
std::map<std::wstring, std::wstring> switches_;
std::vector<std::wstring> loose_values_;
DISALLOW_EVIL_CONSTRUCTORS(CommandLine::Data);
};
CommandLine::CommandLine()
: we_own_data_(false), // The Singleton class will manage it for us.
data_(Singleton<Data>::get()) {
}
CommandLine::CommandLine(const wstring& command_line)
: we_own_data_(true),
data_(new Data(command_line)) {
}
CommandLine::~CommandLine() {
if (we_own_data_)
delete data_;
}
bool CommandLine::HasSwitch(const wstring& switch_string) const {
wstring lowercased_switch(switch_string);
Lowercase(&lowercased_switch);
return data_->switches().find(lowercased_switch) != data_->switches().end();
}
wstring CommandLine::GetSwitchValue(const wstring& switch_string) const {
wstring lowercased_switch(switch_string);
Lowercase(&lowercased_switch);
const map<wstring, wstring>::const_iterator result =
data_->switches().find(lowercased_switch);
if (result == data_->switches().end()) {
return L"";
} else {
return result->second;
}
}
size_t CommandLine::GetLooseValueCount() const {
return data_->loose_values().size();
}
CommandLine::LooseValueIterator CommandLine::GetLooseValuesBegin() const {
return data_->loose_values().begin();
}
CommandLine::LooseValueIterator CommandLine::GetLooseValuesEnd() const {
return data_->loose_values().end();
}
std::wstring CommandLine::command_line_string() const {
return data_->command_line_string();
}
std::wstring CommandLine::program() const {
return data_->program();
}
// static
void CommandLine::AppendSwitch(wstring* command_line_string,
const wstring& switch_string) {
DCHECK(command_line_string);
command_line_string->append(L" ");
command_line_string->append(kSwitchPrefixes[0]);
command_line_string->append(switch_string);
}
// static
void CommandLine::AppendSwitchWithValue(wstring* command_line_string,
const wstring& switch_string,
const wstring& value_string) {
AppendSwitch(command_line_string, switch_string);
if (value_string.empty())
return;
command_line_string->append(kSwitchValueSeparator);
// NOTE(jhughes): If the value contains a quotation mark at one
// end but not both, you may get unusable output.
if ((value_string.find(L" ") != std::wstring::npos) &&
(value_string[0] != L'"') &&
(value_string[value_string.length() - 1] != L'"')) {
// need to provide quotes
StringAppendF(command_line_string, L"\"%s\"", value_string.c_str());
} else {
command_line_string->append(value_string);
}
}

119
base/command_line.h Normal file

@ -0,0 +1,119 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This file contains a class that can be used to extract the salient
// elements of a command line in a relatively lightweight manner.
// Switches can optionally have a value attached using an equals sign,
// as in "-switch=value". Arguments that aren't prefixed with a
// switch prefix are considered "loose parameters". Switch names
// are case-insensitive.
#ifndef BASE_COMMAND_LINE_H__
#define BASE_COMMAND_LINE_H__
#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
class CommandLine {
public:
// Creates a parsed version of the command line used to launch
// the current process.
CommandLine();
// Creates a parsed version of the given command-line string.
// The program name is assumed to be the first item in the string.
CommandLine(const std::wstring& command_line);
~CommandLine();
// Returns true if this command line contains the given switch.
// (Switch names are case-insensitive.)
bool HasSwitch(const std::wstring& switch_string) const;
// Returns the value associated with the given switch. If the
// switch has no value or isn't present, this method returns
// the empty string.
std::wstring GetSwitchValue(const std::wstring& switch_string) const;
// Returns the number of "loose values" found in the command line.
// Loose values are arguments that aren't switches.
// (The program name is also excluded from the set of loose values.)
size_t GetLooseValueCount() const;
typedef std::vector<std::wstring>::const_iterator LooseValueIterator;
// Returns a const_iterator to the list of loose values.
LooseValueIterator GetLooseValuesBegin() const;
// Returns the end const_iterator for the list of loose values.
LooseValueIterator GetLooseValuesEnd() const;
// Simply returns the original command line string.
std::wstring command_line_string() const;
// Returns the program part of the command line string (the first item).
std::wstring program() const;
// An array containing the prefixes that identify an argument as
// a switch.
static const wchar_t* const kSwitchPrefixes[];
// The string that's used to separate switches from their values.
static const wchar_t kSwitchValueSeparator[];
// Appends the given switch string (preceded by a space and a switch
// prefix) to the given string.
static void AppendSwitch(std::wstring* command_line_string,
const std::wstring& switch_string);
// Appends the given switch string (preceded by a space and a switch
// prefix) to the given string, with the given value attached.
static void AppendSwitchWithValue(std::wstring* command_line_string,
const std::wstring& switch_string,
const std::wstring& value_string);
private:
class Data;
// True if we are responsible for deleting our |data_| pointer. In some cases
// we cache the result of parsing the command line and |data_|'s lifetime is
// managed by someone else (e.g., the |Singleton| class).
bool we_own_data_;
// A pointer to the parsed version of the command line.
Data* data_;
DISALLOW_EVIL_CONSTRUCTORS(CommandLine);
};
#endif // BASE_COMMAND_LINE_H__

@ -0,0 +1,125 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class CommandLineTest : public testing::Test {
};
};
TEST(CommandLineTest, CommandLineConstructor) {
CommandLine cl(L"program --foo= -bAr /Spaetzel=pierogi /Baz flim "
L"--other-switches=\"--dog=canine --cat=feline\" "
L"-spaetzle=Crepe -=loosevalue flan "
L"--input-translation=\"45\"--output-rotation "
L"\"in the time of submarines...\"");
EXPECT_FALSE(cl.command_line_string().empty());
EXPECT_FALSE(cl.HasSwitch(L"cruller"));
EXPECT_FALSE(cl.HasSwitch(L"flim"));
EXPECT_FALSE(cl.HasSwitch(L"program"));
EXPECT_FALSE(cl.HasSwitch(L"dog"));
EXPECT_FALSE(cl.HasSwitch(L"cat"));
EXPECT_FALSE(cl.HasSwitch(L"output-rotation"));
EXPECT_EQ(L"program", cl.program());
EXPECT_TRUE(cl.HasSwitch(L"foo"));
EXPECT_TRUE(cl.HasSwitch(L"bar"));
EXPECT_TRUE(cl.HasSwitch(L"baz"));
EXPECT_TRUE(cl.HasSwitch(L"spaetzle"));
EXPECT_TRUE(cl.HasSwitch(L"SPAETZLE"));
EXPECT_TRUE(cl.HasSwitch(L"other-switches"));
EXPECT_TRUE(cl.HasSwitch(L"input-translation"));
EXPECT_EQ(L"Crepe", cl.GetSwitchValue(L"spaetzle"));
EXPECT_EQ(L"", cl.GetSwitchValue(L"Foo"));
EXPECT_EQ(L"", cl.GetSwitchValue(L"bar"));
EXPECT_EQ(L"", cl.GetSwitchValue(L"cruller"));
EXPECT_EQ(L"--dog=canine --cat=feline", cl.GetSwitchValue(L"other-switches"));
EXPECT_EQ(L"45--output-rotation", cl.GetSwitchValue(L"input-translation"));
EXPECT_EQ(3, cl.GetLooseValueCount());
CommandLine::LooseValueIterator iter = cl.GetLooseValuesBegin();
EXPECT_EQ(L"flim", *iter);
++iter;
EXPECT_EQ(L"flan", *iter);
++iter;
EXPECT_EQ(L"in the time of submarines...", *iter);
++iter;
EXPECT_TRUE(iter == cl.GetLooseValuesEnd());
}
// These test the command line used to invoke the unit test.
TEST(CommandLineTest, DefaultConstructor) {
CommandLine cl;
EXPECT_FALSE(cl.command_line_string().empty());
EXPECT_FALSE(cl.program().empty());
}
// Tests behavior with an empty input string.
TEST(CommandLineTest, EmptyString) {
CommandLine cl(L"");
EXPECT_TRUE(cl.command_line_string().empty());
EXPECT_TRUE(cl.program().empty());
EXPECT_EQ(0, cl.GetLooseValueCount());
}
// Test static functions for appending switches to a command line.
TEST(CommandLineTest, AppendSwitches) {
std::wstring cl_string = L"Program";
std::wstring switch1 = L"switch1";
std::wstring switch2 = L"switch2";
std::wstring value = L"value";
std::wstring switch3 = L"switch3";
std::wstring value3 = L"a value with spaces";
std::wstring switch4 = L"switch4";
std::wstring value4 = L"\"a value with quotes\"";
CommandLine::AppendSwitch(&cl_string, switch1);
CommandLine::AppendSwitchWithValue(&cl_string, switch2, value);
CommandLine::AppendSwitchWithValue(&cl_string, switch3, value3);
CommandLine::AppendSwitchWithValue(&cl_string, switch4, value4);
CommandLine cl(cl_string);
EXPECT_TRUE(cl.HasSwitch(switch1));
EXPECT_TRUE(cl.HasSwitch(switch2));
EXPECT_EQ(value, cl.GetSwitchValue(switch2));
EXPECT_TRUE(cl.HasSwitch(switch3));
EXPECT_EQ(value3, cl.GetSwitchValue(switch3));
EXPECT_TRUE(cl.HasSwitch(switch2));
EXPECT_EQ(value4.substr(1, value4.length() - 2), cl.GetSwitchValue(switch4));
}

464
base/condition_variable.cc Normal file

@ -0,0 +1,464 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "base/condition_variable.h"
#include <stack>
#include "base/lock.h"
#include "base/logging.h"
ConditionVariable::ConditionVariable(Lock* user_lock)
: user_lock_(*user_lock),
run_state_(RUNNING),
allocation_counter_(0),
recycling_list_size_(0) {
DCHECK(user_lock);
}
ConditionVariable::~ConditionVariable() {
AutoLock auto_lock(internal_lock_);
run_state_ = SHUTDOWN; // Prevent any more waiting.
DCHECK_EQ(recycling_list_size_, allocation_counter_);
if (recycling_list_size_ != allocation_counter_) { // Rare shutdown problem.
// There are threads of execution still in this->TimedWait() and yet the
// caller has instigated the destruction of this instance :-/.
// A common reason for such "overly hasty" destruction is that the caller
// was not willing to wait for all the threads to terminate. Such hasty
// actions are a violation of our usage contract, but we'll give the
// waiting thread(s) one last chance to exit gracefully (prior to our
// destruction).
// Note: waiting_list_ *might* be empty, but recycling is still pending.
AutoUnlock auto_unlock(internal_lock_);
Broadcast(); // Make sure all waiting threads have been signaled.
Sleep(10); // Give threads a chance to grab internal_lock_.
// All contained threads should be blocked on user_lock_ by now :-).
} // Reacquire internal_lock_.
DCHECK_EQ(recycling_list_size_, allocation_counter_);
}
// Wait() atomically releases the caller's lock as it starts to Wait, and then
// reacquires it when it is signaled.
void ConditionVariable::TimedWait(const TimeDelta& max_time) {
Event* waiting_event;
HANDLE handle;
{
AutoLock auto_lock(internal_lock_);
if (RUNNING != run_state_) return; // Destruction in progress.
waiting_event = GetEventForWaiting();
handle = waiting_event->handle();
DCHECK(handle);
} // Release internal_lock.
{
AutoUnlock unlock(user_lock_); // Release caller's lock
WaitForSingleObject(handle, static_cast<DWORD>(max_time.InMilliseconds()));
// Minimize spurious signal creation window by recycling asap.
AutoLock auto_lock(internal_lock_);
RecycleEvent(waiting_event);
// Release internal_lock_
} // Reacquire callers lock to depth at entry.
}
// Broadcast() is guaranteed to signal all threads that were waiting (i.e., had
// a cv_event internally allocated for them) before Broadcast() was called.
void ConditionVariable::Broadcast() {
std::stack<HANDLE> handles; // See FAQ-question-10.
{
AutoLock auto_lock(internal_lock_);
if (waiting_list_.IsEmpty())
return;
while (!waiting_list_.IsEmpty())
// This is not a leak from waiting_list_. See FAQ-question 12.
handles.push(waiting_list_.PopBack()->handle());
} // Release internal_lock_.
while (!handles.empty()) {
SetEvent(handles.top());
handles.pop();
}
}
// Signal() will select one of the waiting threads, and signal it (signal its
// cv_event). For better performance we signal the thread that went to sleep
// most recently (LIFO). If we want fairness, then we wake the thread that has
// been sleeping the longest (FIFO).
void ConditionVariable::Signal() {
HANDLE handle;
{
AutoLock auto_lock(internal_lock_);
if (waiting_list_.IsEmpty())
return; // No one to signal.
// Only performance option should be used.
// This is not a leak from waiting_list. See FAQ-question 12.
handle = waiting_list_.PopBack()->handle(); // LIFO.
} // Release internal_lock_.
SetEvent(handle);
}
// GetEventForWaiting() provides a unique cv_event for any caller that needs to
// wait. This means that (worst case) we may over time create as many cv_event
// objects as there are threads simultaneously using this instance's Wait()
// functionality.
ConditionVariable::Event* ConditionVariable::GetEventForWaiting() {
// We hold internal_lock, courtesy of Wait().
Event* cv_event;
if (0 == recycling_list_size_) {
DCHECK(recycling_list_.IsEmpty());
cv_event = new Event();
cv_event->InitListElement();
allocation_counter_++;
// CHECK_NE is not defined in our codebase, so we have to use CHECK
CHECK(cv_event->handle());
} else {
cv_event = recycling_list_.PopFront();
recycling_list_size_--;
}
waiting_list_.PushBack(cv_event);
return cv_event;
}
// RecycleEvent() takes a cv_event that was previously used for Wait()ing, and
// recycles it for use in future Wait() calls for this or other threads.
// Note that there is a tiny chance that the cv_event is still signaled when we
// obtain it, and that can cause spurious signals (if/when we re-use the
// cv_event), but such is quite rare (see FAQ-question-5).
void ConditionVariable::RecycleEvent(Event* used_event) {
// We hold internal_lock, courtesy of Wait().
// If the cv_event timed out, then it is necessary to remove it from
// waiting_list_. If it was selected by Broadcast() or Signal(), then it is
// already gone.
used_event->Extract(); // Possibly redundant
recycling_list_.PushBack(used_event);
recycling_list_size_++;
}
//------------------------------------------------------------------------------
// The next section provides the implementation for the private Event class.
//------------------------------------------------------------------------------
// Event provides a doubly-linked-list of events for use exclusively by the
// ConditionVariable class.
// This custom container was crafted because no simple combination of STL
// classes appeared to support the functionality required. The specific
// unusual requirement for a linked-list-class is support for the Extract()
// method, which can remove an element from a list, potentially for insertion
// into a second list. Most critically, the Extract() method is idempotent,
// turning the indicated element into an extracted singleton whether it was
// contained in a list or not. This functionality allows one (or more) of
// threads to do the extraction. The iterator that identifies this extractable
// element (in this case, a pointer to the list element) can be used after
// arbitrary manipulation of the (possibly) enclosing list container. In
// general, STL containers do not provide iterators that can be used across
// modifications (insertions/extractions) of the enclosing containers, and
// certainly don't provide iterators that can be used if the identified
// element is *deleted* (removed) from the container.
// It is possible to use multiple redundant containers, such as an STL list,
// and an STL map, to achieve similar container semantics. This container has
// only O(1) methods, while the corresponding (multiple) STL container approach
// would have more complex O(log(N)) methods (yeah... N isn't that large).
// Multiple containers also makes correctness more difficult to assert, as
// data is redundantly stored and maintained, which is generally evil.
ConditionVariable::Event::Event() : handle_(0) {
next_ = prev_ = this; // Self referencing circular.
}
ConditionVariable::Event::~Event() {
if (0 == handle_) {
// This is the list holder
while (!IsEmpty()) {
Event* cv_event = PopFront();
DCHECK(cv_event->ValidateAsItem());
delete cv_event;
}
}
DCHECK(IsSingleton());
if (0 != handle_) {
int ret_val = CloseHandle(handle_);
DCHECK(ret_val);
}
}
// Change a container instance permanently into an element of a list.
void ConditionVariable::Event::InitListElement() {
DCHECK(!handle_);
handle_ = CreateEvent(NULL, false, false, NULL);
CHECK(handle_);
}
// Methods for use on lists.
bool ConditionVariable::Event::IsEmpty() const {
DCHECK(ValidateAsList());
return IsSingleton();
}
void ConditionVariable::Event::PushBack(Event* other) {
DCHECK(ValidateAsList());
DCHECK(other->ValidateAsItem());
DCHECK(other->IsSingleton());
// Prepare other for insertion.
other->prev_ = prev_;
other->next_ = this;
// Cut into list.
prev_->next_ = other;
prev_ = other;
DCHECK(ValidateAsDistinct(other));
}
ConditionVariable::Event* ConditionVariable::Event::PopFront() {
DCHECK(ValidateAsList());
DCHECK(!IsSingleton());
return next_->Extract();
}
ConditionVariable::Event* ConditionVariable::Event::PopBack() {
DCHECK(ValidateAsList());
DCHECK(!IsSingleton());
return prev_->Extract();
}
// Methods for use on list elements.
// Accessor method.
HANDLE ConditionVariable::Event::handle() const {
DCHECK(ValidateAsItem());
return handle_;
}
// Pull an element from a list (if it's in one).
ConditionVariable::Event* ConditionVariable::Event::Extract() {
DCHECK(ValidateAsItem());
if (!IsSingleton()) {
// Stitch neighbors together.
next_->prev_ = prev_;
prev_->next_ = next_;
// Make extractee into a singleton.
prev_ = next_ = this;
}
DCHECK(IsSingleton());
return this;
}
// Method for use on a list element or on a list.
bool ConditionVariable::Event::IsSingleton() const {
DCHECK(ValidateLinks());
return next_ == this;
}
// Provide pre/post conditions to validate correct manipulations.
bool ConditionVariable::Event::ValidateAsDistinct(Event* other) const {
return ValidateLinks() && other->ValidateLinks() && (this != other);
}
bool ConditionVariable::Event::ValidateAsItem() const {
return (0 != handle_) && ValidateLinks();
}
bool ConditionVariable::Event::ValidateAsList() const {
return (0 == handle_) && ValidateLinks();
}
bool ConditionVariable::Event::ValidateLinks() const {
// Make sure both of our neighbors have links that point back to us.
// We don't do the O(n) check and traverse the whole loop, and instead only
// do a local check to (and returning from) our immediate neighbors.
return (next_->prev_ == this) && (prev_->next_ == this);
}
/*
FAQ On subtle implementation details:
1) What makes this problem subtle? Please take a look at "Strategies
for Implementing POSIX Condition Variables on Win32" by Douglas
C. Schmidt and Irfan Pyarali.
http://www.cs.wustl.edu/~schmidt/win32-cv-1.html It includes
discussions of numerous flawed strategies for implementing this
functionality. I'm not convinced that even the final proposed
implementation has semantics that are as nice as this implementation
(especially with regard to Broadcast() and the impact on threads that
try to Wait() after a Broadcast() has been called, but before all the
original waiting threads have been signaled).
2) Why can't you use a single wait_event for all threads that call
Wait()? See FAQ-question-1, or consider the following: If a single
event were used, then numerous threads calling Wait() could release
their cs locks, and be preempted just before calling
WaitForSingleObject(). If a call to Broadcast() was then presented on
a second thread, it would be impossible to actually signal all
waiting(?) threads. Some number of SetEvent() calls *could* be made,
but there could be no guarantee that those led to to more than one
signaled thread (SetEvent()'s may be discarded after the first!), and
there could be no guarantee that the SetEvent() calls didn't just
awaken "other" threads that hadn't even started waiting yet (oops).
Without any limit on the number of requisite SetEvent() calls, the
system would be forced to do many such calls, allowing many new waits
to receive spurious signals.
3) How does this implementation cause spurious signal events? The
cause in this implementation involves a race between a signal via
time-out and a signal via Signal() or Broadcast(). The series of
actions leading to this are:
a) Timer fires, and a waiting thread exits the line of code:
WaitForSingleObject(waiting_event, max_time.InMilliseconds());
b) That thread (in (a)) is randomly pre-empted after the above line,
leaving the waiting_event reset (unsignaled) and still in the
waiting_list_.
c) A call to Signal() (or Broadcast()) on a second thread proceeds, and
selects the waiting cv_event (identified in step (b)) as the event to revive
via a call to SetEvent().
d) The Signal() method (step c) calls SetEvent() on waiting_event (step b).
e) The waiting cv_event (step b) is now signaled, but no thread is
waiting on it.
f) When that waiting_event (step b) is reused, it will immediately
be signaled (spuriously).
4) Why do you recycle events, and cause spurious signals? First off,
the spurious events are very rare. They can only (I think) appear
when the race described in FAQ-question-3 takes place. This should be
very rare. Most(?) uses will involve only timer expiration, or only
Signal/Broadcast() actions. When both are used, it will be rare that
the race will appear, and it would require MANY Wait() and signaling
activities. If this implementation did not recycle events, then it
would have to create and destroy events for every call to Wait().
That allocation/deallocation and associated construction/destruction
would be costly (per wait), and would only be a rare benefit (when the
race was "lost" and a spurious signal took place). That would be bad
(IMO) optimization trade-off. Finally, such spurious events are
allowed by the specification of condition variables (such as
implemented in Vista), and hence it is better if any user accommodates
such spurious events (see usage note in condition_variable.h).
5) Why don't you reset events when you are about to recycle them, or
about to reuse them, so that the spurious signals don't take place?
The thread described in FAQ-question-3 step c may be pre-empted for an
arbitrary length of time before proceeding to step d. As a result,
the wait_event may actually be re-used *before* step (e) is reached.
As a result, calling reset would not help significantly.
6) How is it that the callers lock is released atomically with the
entry into a wait state? We commit to the wait activity when we
allocate the wait_event for use in a given call to Wait(). This
allocation takes place before the caller's lock is released (and
actually before our internal_lock_ is released). That allocation is
the defining moment when "the wait state has been entered," as that
thread *can* now be signaled by a call to Broadcast() or Signal().
Hence we actually "commit to wait" before releasing the lock, making
the pair effectively atomic.
8) Why do you need to lock your data structures during waiting, as the
caller is already in possession of a lock? We need to Acquire() and
Release() our internal lock during Signal() and Broadcast(). If we tried
to use a callers lock for this purpose, we might conflict with their
external use of the lock. For example, the caller may use to consistently
hold a lock on one thread while calling Signal() on another, and that would
block Signal().
9) Couldn't a more efficient implementation be provided if you
preclude using more than one external lock in conjunction with a
single ConditionVariable instance? Yes, at least it could be viewed
as a simpler API (since you don't have to reiterate the lock argument
in each Wait() call). One of the constructors now takes a specific
lock as an argument, and a there are corresponding Wait() calls that
don't specify a lock now. It turns that the resulting implmentation
can't be made more efficient, as the internal lock needs to be used by
Signal() and Broadcast(), to access internal data structures. As a
result, I was not able to utilize the user supplied lock (which is
being used by the user elsewhere presumably) to protect the private
member access.
9) Since you have a second lock, how can be be sure that there is no
possible deadlock scenario? Our internal_lock_ is always the last
lock acquired, and the first one released, and hence a deadlock (due
to critical section problems) is impossible as a consequence of our
lock.
10) When doing a Broadcast(), why did you copy all the events into
an STL queue, rather than making a linked-loop, and iterating over it?
The iterating during Broadcast() is done so outside the protection
of the internal lock. As a result, other threads, such as the thread
wherein a related event is waiting, could asynchronously manipulate
the links around a cv_event. As a result, the link structure cannot
be used outside a lock. Broadcast() could iterate over waiting
events by cycling in-and-out of the protection of the internal_lock,
but that appears more expensive than copying the list into an STL
stack.
11) Why did the lock.h file need to be modified so much for this
change? Central to a Condition Variable is the atomic release of a
lock during a Wait(). This places Wait() functionality exactly
mid-way between the two classes, Lock and Condition Variable. Given
that there can be nested Acquire()'s of locks, and Wait() had to
Release() completely a held lock, it was necessary to augment the Lock
class with a recursion counter. Even more subtle is the fact that the
recursion counter (in a Lock) must be protected, as many threads can
access it asynchronously. As a positive fallout of this, there are
now some DCHECKS to be sure no one Release()s a Lock more than they
Acquire()ed it, and there is ifdef'ed functionality that can detect
nested locks (legal under windows, but not under Posix).
12) Why is it that the cv_events removed from list in Broadcast() and Signal()
are not leaked? How are they recovered?? The cv_events that appear to leak are
taken from the waiting_list_. For each element in that list, there is currently
a thread in or around the WaitForSingleObject() call of Wait(), and those
threads have references to these otherwise leaked events. They are passed as
arguments to be recycled just aftre returning from WaitForSingleObject().
13) Why did you use a custom container class (the linked list), when STL has
perfectly good containers, such as an STL list? The STL list, as with any
container, does not guarantee the utility of an iterator across manipulation
(such as insertions and deletions) of the underlying container. The custom
double-linked-list container provided that assurance. I don't believe any
combination of STL containers provided the services that were needed at the same
O(1) efficiency as the custom linked list. The unusual requirement
for the container class is that a reference to an item within a container (an
iterator) needed to be maintained across an arbitrary manipulation of the
container. This requirement exposes itself in the Wait() method, where a
waiting_event must be selected prior to the WaitForSingleObject(), and then it
must be used as part of recycling to remove the related instance from the
waiting_list. A hash table (STL map) could be used, but I was embarrased to
use a complex and relatively low efficiency container when a doubly linked list
provided O(1) performance in all required operations. Since other operations
to provide performance-and/or-fairness required queue (FIFO) and list (LIFO)
containers, I would also have needed to use an STL list/queue as well as an STL
map. In the end I decided it would be "fun" to just do it right, and I
put so many assertions (DCHECKs) into the container class that it is trivial to
code review and validate its correctness.
*/

195
base/condition_variable.h Normal file

@ -0,0 +1,195 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ConditionVariable is a reasonable attempt at simulating
// the newer Posix and Vista-only construct for condition variable
// synchronization. This functionality is very helpful for having several
// threads wait for an event, as is common with a thread pool
// managed by a master. The meaning of such an event in the
// (worker) thread pool scenario is that additional tasks are
// now available for processing. It is used in Chrome in the
// DNS prefetching system to notify worker threads that a queue
// now has items (tasks) which need to be tended to.
// A related use would have a pool manager waiting on a
// ConditionVariable, waiting for a thread in the pool to announce
// (signal) that there is now more room in a (bounded size) communications
// queue for the manager to deposit tasks, or, as a second example, that
// the queue of tasks is completely empty and all workers are waiting.
// USAGE NOTE 1: spurious signal events are possible with this and
// most implementations of condition variables. As a result, be
// *sure* to retest your condition before proceeding. The following
// is a good example of doing this correctly:
// while (!work_to_be_done()) Wait(...);
// In contrast do NOT do the following:
// if (!work_to_be_done()) Wait(...); // Don't do this.
// Especially avoid the above if you are relying on some other thread only
// issuing a signal up *if* there is work-to-do. There can/will
// be spurious signals. Recheck state on waiting thread before
// assuming the signal was intentional. Caveat caller ;-).
// USAGE NOTE 2: Broadcast() frees up all waiting threads at once,
// which leads to contention for the locks they all held when they
// called Wait(). This results in POOR performance. A much better
// approach to getting a lot of threads out of Wait() is to have each
// thread (upon exiting Wait()) call Signal() to free up another
// Wait'ing thread. Look at condition_variable_unittest.cc for
// both examples.
// Broadcast() can be used nicely during teardown, as it gets the job
// done, and leaves no sleeping threads... and performance is less
// critical at that point.
// The semantics of Broadcast() are carefully crafted so that *all*
// threads that were waiting when the request was made will indeed
// get signaled. Some implementations mess up, and don't signal them
// all, while others allow the wait to be effectively turned off (for
// for a while while waiting threads come around). This implementation
// appears correct, as it will not "lose" any signals, and will guarantee
// that all threads get signaled by Broadcast().
// This implementation offers support for "performance" in its selection of
// which thread to revive. Performance, in direct contrast with "fairness,"
// assures that the thread that most recently began to Wait() is selected by
// Signal to revive. Fairness would (if publicly supported) assure that the
// thread that has Wait()ed the longest is selected. The default policy
// may improve performance, as the selected thread may have a greater chance of
// having some of its stack data in various CPU caches.
// For a discussion of the many very subtle implementation details, see the FAQ
// at the end of condition_variable.cc.
#ifndef BASE_CONDITION_VARIABLE_H__
#define BASE_CONDITION_VARIABLE_H__
#include "base/lock.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
class Lock;
class ConditionVariable {
public:
// Construct a cv for use with ONLY one user lock.
explicit ConditionVariable(Lock* user_lock);
~ConditionVariable();
// Wait() releases the caller's critical section atomically as it starts to
// sleep, and the reacquires it when it is signaled.
void TimedWait(const TimeDelta& max_time);
void Wait() {
// Default to "wait forever" timing, which means have to get a Signal()
// or Broadcast() to come out of this wait state.
TimedWait(TimeDelta::FromMilliseconds(INFINITE));
}
// Broadcast() revives all waiting threads.
void Broadcast();
// Signal() revives one waiting thread.
void Signal();
private:
// Define Event class that is used to form circularly linked lists.
// The list container is an element with NULL as its handle_ value.
// The actual list elements have a non-zero handle_ value.
// All calls to methods MUST be done under protection of a lock so that links
// can be validated. Without the lock, some links might asynchronously
// change, and the assertions would fail (as would list change operations).
class Event {
public:
// Default constructor with no arguments creates a list container.
Event();
~Event();
// InitListElement transitions an instance from a container, to an element.
void InitListElement();
// Methods for use on lists.
bool IsEmpty() const;
void PushBack(Event* other);
Event* PopFront();
Event* PopBack();
// Methods for use on list elements.
// Accessor method.
HANDLE handle() const;
// Pull an element from a list (if it's in one).
Event* Extract();
// Method for use on a list element or on a list.
bool IsSingleton() const;
private:
// Provide pre/post conditions to validate correct manipulations.
bool ValidateAsDistinct(Event* other) const;
bool ValidateAsItem() const;
bool ValidateAsList() const;
bool ValidateLinks() const;
HANDLE handle_;
Event* next_;
Event* prev_;
DISALLOW_EVIL_CONSTRUCTORS(Event);
};
// Note that RUNNING is an unlikely number to have in RAM by accident.
// This helps with defensive destructor coding in the face of user error.
enum RunState { SHUTDOWN = 0, RUNNING = 64213 };
// Internal implementation methods supporting Wait().
Event* GetEventForWaiting();
void RecycleEvent(Event* used_event);
RunState run_state_;
// Private critical section for access to member data.
Lock internal_lock_;
// Lock that is acquired before calling Wait().
Lock& user_lock_;
// Events that threads are blocked on.
Event waiting_list_;
// Free list for old events.
Event recycling_list_;
int recycling_list_size_;
// The number of allocated, but not yet deleted events.
int allocation_counter_;
DISALLOW_EVIL_CONSTRUCTORS(ConditionVariable);
};
#endif // BASE_CONDITION_VARIABLE_H__

@ -0,0 +1,707 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Multi-threaded tests of ConditionVariable class.
#include <time.h>
#include <algorithm>
#include <vector>
#include "base/check_handler.h"
#include "base/condition_variable.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/spin_wait.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
//------------------------------------------------------------------------------
// Define our test class, with several common variables.
//------------------------------------------------------------------------------
class ConditionVariableTest : public testing::Test {
public:
const TimeDelta kZeroMs;
const TimeDelta kTenMs;
const TimeDelta kThirtyMs;
const TimeDelta kFortyFiveMs;
const TimeDelta kSixtyMs;
const TimeDelta kOneHundredMs;
explicit ConditionVariableTest()
: kZeroMs(TimeDelta::FromMilliseconds(0)),
kTenMs(TimeDelta::FromMilliseconds(10)),
kThirtyMs(TimeDelta::FromMilliseconds(30)),
kFortyFiveMs(TimeDelta::FromMilliseconds(45)),
kSixtyMs(TimeDelta::FromMilliseconds(60)),
kOneHundredMs(TimeDelta::FromMilliseconds(100)) {
}
};
//------------------------------------------------------------------------------
// Define a class that will control activities an several multi-threaded tests.
// The general structure of multi-threaded tests is that a test case will
// construct an instance of a WorkQueue. The WorkQueue will spin up some
// threads and control them thoughout their lifetime, as well as maintaining
// a central respository of the work thread's activity. Finally, the WorkQueue
// will command the the worker threads to terminate. At that point, the test
// cases will validate that the WorkQueue has records showing that the desired
// activities were performed.
//------------------------------------------------------------------------------
// Forward declare the WorkerProcess task
static DWORD WINAPI WorkerProcess(void* p);
// Callers are responsible for synchronizing access to the following class.
// The WorkQueue::lock_, as accessed via WorkQueue::lock(), should be used for
// all synchronized access.
class WorkQueue {
public:
explicit WorkQueue(int thread_count);
~WorkQueue();
//----------------------------------------------------------------------------
// Worker threads only call the following methods.
// They should use the lock to get exclusive access.
int GetThreadId(); // Get an ID assigned to a thread..
bool EveryIdWasAllocated() const; // Indicates that all IDs were handed out.
TimeDelta GetAnAssignment(int thread_id); // Get a work task duration.
void WorkIsCompleted(int thread_id);
int task_count() const;
bool allow_help_requests() const; // Workers can signal more workers.
bool shutdown() const; // Check if shutdown has been requested.
int shutdown_task_count() const;
void thread_shutting_down();
Lock* lock();
ConditionVariable* work_is_available();
ConditionVariable* all_threads_have_ids();
ConditionVariable* no_more_tasks();
//----------------------------------------------------------------------------
// The rest of the methods are for use by the controlling master thread (the
// test case code).
void ResetHistory();
int GetMinCompletionsByWorkerThread() const;
int GetMaxCompletionsByWorkerThread() const;
int GetNumThreadsTakingAssignments() const;
int GetNumThreadsCompletingTasks() const;
int GetNumberOfCompletedTasks() const;
void SetWorkTime(TimeDelta delay);
void SetTaskCount(int count);
void SetAllowHelp(bool allow);
void SetShutdown();
private:
// Both worker threads and controller use the following to synchronize.
Lock lock_;
ConditionVariable work_is_available_; // To tell threads there is work.
// Conditions to notify the controlling process (if it is interested).
ConditionVariable all_threads_have_ids_; // All threads are running.
ConditionVariable no_more_tasks_; // Task count is zero.
const int thread_count_;
scoped_array<HANDLE> handles_;
std::vector<int> assignment_history_; // Number of assignment per worker.
std::vector<int> completion_history_; // Number of completions per worker.
int thread_started_counter_; // Used to issue unique id to workers.
int shutdown_task_count_; // Number of tasks told to shutdown
int task_count_; // Number of assignment tasks waiting to be processed.
TimeDelta worker_delay_; // Time each task takes to complete.
bool allow_help_requests_; // Workers can signal more workers.
bool shutdown_; // Set when threads need to terminate.
};
//------------------------------------------------------------------------------
// Define the standard worker task. Several tests will spin out many of these
// threads.
//------------------------------------------------------------------------------
// The multithread tests involve several threads with a task to perform as
// directed by an instance of the class WorkQueue.
// The task is to:
// a) Check to see if there are more tasks (there is a task counter).
// a1) Wait on condition variable if there are no tasks currently.
// b) Call a function to see what should be done.
// c) Do some computation based on the number of milliseconds returned in (b).
// d) go back to (a).
// WorkerProcess() implements the above task for all threads.
// It calls the controlling object to tell the creator about progress, and to
// ask about tasks.
static DWORD WINAPI WorkerProcess(void* p) {
int thread_id;
class WorkQueue* queue = reinterpret_cast<WorkQueue*>(p);
{
AutoLock auto_lock(*queue->lock());
thread_id = queue->GetThreadId();
if (queue->EveryIdWasAllocated())
queue->all_threads_have_ids()->Signal(); // Tell creator we're ready.
}
Lock private_lock; // Used to waste time on "our work".
while (1) { // This is the main consumer loop.
TimeDelta work_time;
bool could_use_help;
{
AutoLock auto_lock(*queue->lock());
while (0 == queue->task_count() && !queue->shutdown()) {
queue->work_is_available()->Wait();
}
if (queue->shutdown()) {
// Ack the notification of a shutdown message back to the controller.
queue->thread_shutting_down();
return 0; // Terminate.
}
// Get our task duration from the queue.
work_time = queue->GetAnAssignment(thread_id);
could_use_help = (queue->task_count() > 0) &&
queue->allow_help_requests();
} // Release lock
// Do work (outside of locked region.
if (could_use_help)
queue->work_is_available()->Signal(); // Get help from other threads.
if (work_time > TimeDelta::FromMilliseconds(0)) {
// We could just sleep(), but we'll instead further exercise the
// condition variable class, and do a timed wait.
AutoLock auto_lock(private_lock);
ConditionVariable private_cv(&private_lock);
private_cv.TimedWait(work_time); // Unsynchronized waiting.
}
{
AutoLock auto_lock(*queue->lock());
// Send notification that we completed our "work."
queue->WorkIsCompleted(thread_id);
}
}
}
//------------------------------------------------------------------------------
// The next section contains the actual tests.
//------------------------------------------------------------------------------
TEST_F(ConditionVariableTest, StartupShutdownTest) {
Lock lock;
// First try trivial startup/shutdown.
{
ConditionVariable cv1(&lock);
} // Call for cv1 destruction.
// Exercise with at least a few waits.
ConditionVariable cv(&lock);
lock.Acquire();
cv.TimedWait(kTenMs); // Wait for 10 ms.
cv.TimedWait(kTenMs); // Wait for 10 ms.
lock.Release();
lock.Acquire();
cv.TimedWait(kTenMs); // Wait for 10 ms.
cv.TimedWait(kTenMs); // Wait for 10 ms.
cv.TimedWait(kTenMs); // Wait for 10 ms.
lock.Release();
} // Call for cv destruction.
TEST_F(ConditionVariableTest, LockedExpressionTest) {
int i = 0;
Lock lock;
// Old LOCKED_EXPRESSION macro caused syntax errors here.
// ... yes... compiler will optimize this example.
// Syntax error is what I'm after precluding.
if (0)
LOCKED_EXPRESSION(lock, i = 1);
else
LOCKED_EXPRESSION(lock, i = 2);
EXPECT_EQ(2, i);
}
TEST_F(ConditionVariableTest, TimeoutTest) {
Lock lock;
ConditionVariable cv(&lock);
lock.Acquire();
TimeTicks start = TimeTicks::Now();
const TimeDelta WAIT_TIME = TimeDelta::FromMilliseconds(300);
// Allow for clocking rate granularity.
const TimeDelta FUDGE_TIME = TimeDelta::FromMilliseconds(50);
cv.TimedWait(WAIT_TIME + FUDGE_TIME);
TimeDelta duration = TimeTicks::Now() - start;
// We can't use EXPECT_GE here as the TimeDelta class does not support the
// required stream conversion.
EXPECT_TRUE(duration >= WAIT_TIME);
lock.Release();
}
TEST_F(ConditionVariableTest, MultiThreadConsumerTest) {
const int kThreadCount = 10;
WorkQueue queue(kThreadCount); // Start the threads.
Lock private_lock; // Used locally for master to wait.
AutoLock private_held_lock(private_lock);
ConditionVariable private_cv(&private_lock);
{
AutoLock auto_lock(*queue.lock());
while (!queue.EveryIdWasAllocated())
queue.all_threads_have_ids()->Wait();
}
// Wait a bit more to allow threads to reach their wait state.
private_cv.TimedWait(kTenMs);
{
// Since we have no tasks, all threads should be waiting by now.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
// Set up to make one worker do 3 30ms tasks.
queue.ResetHistory();
queue.SetTaskCount(3);
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(false);
}
queue.work_is_available()->Signal(); // Start up one thread.
// Wait to allow solo worker insufficient time to get done.
private_cv.TimedWait(kFortyFiveMs); // Should take about 90 ms.
{
// Check that all work HASN'T completed yet.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(1, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(1, queue.GetNumThreadsCompletingTasks());
EXPECT_GT(2, queue.task_count()); // 2 should have started.
EXPECT_GT(3, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(1, queue.GetNumberOfCompletedTasks());
}
// Wait to allow solo workers to get done.
private_cv.TimedWait(kSixtyMs); // Should take about 45ms more.
{
// Check that all work was done by one thread id.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(1, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(1, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(3, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
// Set up to make each task include getting help from another worker.
queue.ResetHistory();
queue.SetTaskCount(3);
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(true);
}
queue.work_is_available()->Signal(); // But each worker can signal another.
// Wait to allow the 3 workers to get done.
private_cv.TimedWait(kFortyFiveMs); // Should take about 30 ms.
{
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
// Try to ask all workers to help, and only a few will do the work.
queue.ResetHistory();
queue.SetTaskCount(3);
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(false);
}
queue.work_is_available()->Broadcast(); // Make them all try.
// Wait to allow the 3 workers to get done.
private_cv.TimedWait(kFortyFiveMs);
{
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
// Set up to make each task get help from another worker.
queue.ResetHistory();
queue.SetTaskCount(3);
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
}
queue.work_is_available()->Broadcast(); // We already signal all threads.
// Wait to allow the 3 workers to get done.
private_cv.TimedWait(kOneHundredMs);
{
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
// Set up to make each task get help from another worker.
queue.ResetHistory();
queue.SetTaskCount(20);
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(true);
}
queue.work_is_available()->Signal(); // But each worker can signal another.
// Wait to allow the 10 workers to get done.
private_cv.TimedWait(kOneHundredMs); // Should take about 60 ms.
{
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(2, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(2, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
// Same as last test, but with Broadcast().
queue.ResetHistory();
queue.SetTaskCount(20); // 2 tasks per process.
queue.SetWorkTime(kThirtyMs);
queue.SetAllowHelp(true);
}
queue.work_is_available()->Broadcast();
// Wait to allow the 10 workers to get done.
private_cv.TimedWait(kOneHundredMs); // Should take about 60 ms.
{
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(2, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(2, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
queue.SetShutdown();
}
queue.work_is_available()->Broadcast(); // Force check for shutdown.
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
queue.shutdown_task_count() == kThreadCount);
Sleep(10); // Be sure they're all shutdown.
}
TEST_F(ConditionVariableTest, LargeFastTaskTest) {
const int kThreadCount = 200;
WorkQueue queue(kThreadCount); // Start the threads.
Lock private_lock; // Used locally for master to wait.
AutoLock private_held_lock(private_lock);
ConditionVariable private_cv(&private_lock);
{
AutoLock auto_lock(*queue.lock());
while (!queue.EveryIdWasAllocated())
queue.all_threads_have_ids()->Wait();
}
// Wait a bit more to allow threads to reach their wait state.
private_cv.TimedWait(kThirtyMs);
{
// Since we have no tasks, all threads should be waiting by now.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
// Set up to make all workers do (an average of) 20 tasks.
queue.ResetHistory();
queue.SetTaskCount(20 * kThreadCount);
queue.SetWorkTime(kFortyFiveMs);
queue.SetAllowHelp(false);
}
queue.work_is_available()->Broadcast(); // Start up all threads.
// Wait until we've handed out all tasks.
{
AutoLock auto_lock(*queue.lock());
while (queue.task_count() != 0)
queue.no_more_tasks()->Wait();
}
// Wait till the last of the tasks complete.
// Don't bother to use locks: We may not get info in time... but we'll see it
// eventually.
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
20 * kThreadCount ==
queue.GetNumberOfCompletedTasks());
{
// With Broadcast(), every thread should have participated.
// but with racing.. they may not all have done equal numbers of tasks.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_LE(20, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(20 * kThreadCount, queue.GetNumberOfCompletedTasks());
// Set up to make all workers do (an average of) 4 tasks.
queue.ResetHistory();
queue.SetTaskCount(kThreadCount * 4);
queue.SetWorkTime(kFortyFiveMs);
queue.SetAllowHelp(true); // Might outperform Broadcast().
}
queue.work_is_available()->Signal(); // Start up one thread.
// Wait until we've handed out all tasks
{
AutoLock auto_lock(*queue.lock());
while (queue.task_count() != 0)
queue.no_more_tasks()->Wait();
}
// Wait till the last of the tasks complete.
// Don't bother to use locks: We may not get info in time... but we'll see it
// eventually.
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
4 * kThreadCount ==
queue.GetNumberOfCompletedTasks());
{
// With Signal(), every thread should have participated.
// but with racing.. they may not all have done four tasks.
AutoLock auto_lock(*queue.lock());
EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
EXPECT_EQ(0, queue.task_count());
EXPECT_LE(4, queue.GetMaxCompletionsByWorkerThread());
EXPECT_EQ(4 * kThreadCount, queue.GetNumberOfCompletedTasks());
queue.SetShutdown();
}
queue.work_is_available()->Broadcast(); // Force check for shutdown.
// Wait for shutdows to complete.
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
queue.shutdown_task_count() == kThreadCount);
Sleep(10); // Be sure they're all shutdown.
}
//------------------------------------------------------------------------------
// Finally we provide the implementation for the methods in the WorkQueue class.
//------------------------------------------------------------------------------
WorkQueue::WorkQueue(int thread_count)
: lock_(),
work_is_available_(&lock_),
all_threads_have_ids_(&lock_),
no_more_tasks_(&lock_),
thread_count_(thread_count),
handles_(new HANDLE[thread_count]),
assignment_history_(thread_count),
completion_history_(thread_count),
thread_started_counter_(0),
shutdown_task_count_(0),
task_count_(0),
allow_help_requests_(false),
shutdown_(false) {
EXPECT_GE(thread_count_, 1);
ResetHistory();
SetTaskCount(0);
SetWorkTime(TimeDelta::FromMilliseconds(30));
for (int i = 0; i < thread_count_; ++i) {
handles_[i] = CreateThread(NULL, // security.
0, // <64K stack size.
WorkerProcess, // Static function.
reinterpret_cast<void*>(this),
0, // Create running process.
NULL); // OS version of thread id.
EXPECT_NE(reinterpret_cast<void*>(NULL), handles_[i]);
}
}
WorkQueue::~WorkQueue() {
{
AutoLock auto_lock(lock_);
SetShutdown();
}
work_is_available_.Broadcast(); // Tell them all to terminate.
DWORD result = WaitForMultipleObjects(
thread_count_,
&handles_[0],
true, // Wait for all
10000); // Ten seconds max.
for (int i = 0; i < thread_count_; ++i) {
int ret_value = CloseHandle(handles_[i]);
CHECK(ret_value);
handles_[i] = NULL;
}
}
int WorkQueue::GetThreadId() {
DCHECK(!EveryIdWasAllocated());
return thread_started_counter_++; // Give out Unique IDs.
}
bool WorkQueue::EveryIdWasAllocated() const {
return thread_count_ == thread_started_counter_;
}
TimeDelta WorkQueue::GetAnAssignment(int thread_id) {
DCHECK_LT(0, task_count_);
assignment_history_[thread_id]++;
if (0 == --task_count_) {
no_more_tasks_.Signal();
}
return worker_delay_;
}
void WorkQueue::WorkIsCompleted(int thread_id) {
completion_history_[thread_id]++;
}
int WorkQueue::task_count() const {
return task_count_;
}
bool WorkQueue::allow_help_requests() const {
return allow_help_requests_;
}
bool WorkQueue::shutdown() const {
return shutdown_;
}
int WorkQueue::shutdown_task_count() const {
return shutdown_task_count_;
}
void WorkQueue::thread_shutting_down() {
shutdown_task_count_++;
}
Lock* WorkQueue::lock() {
return &lock_;
}
ConditionVariable* WorkQueue::work_is_available() {
return &work_is_available_;
}
ConditionVariable* WorkQueue::all_threads_have_ids() {
return &all_threads_have_ids_;
}
ConditionVariable* WorkQueue::no_more_tasks() {
return &no_more_tasks_;
}
void WorkQueue::ResetHistory() {
for (int i = 0; i < thread_count_; ++i) {
assignment_history_[i] = 0;
completion_history_[i] = 0;
}
}
int WorkQueue::GetMinCompletionsByWorkerThread() const {
int minumum = completion_history_[0];
for (int i = 0; i < thread_count_; ++i)
minumum = std::min(minumum, completion_history_[i]);
return minumum;
}
int WorkQueue::GetMaxCompletionsByWorkerThread() const {
int maximum = completion_history_[0];
for (int i = 0; i < thread_count_; ++i)
maximum = std::max(maximum, completion_history_[i]);
return maximum;
}
int WorkQueue::GetNumThreadsTakingAssignments() const {
int count = 0;
for (int i = 0; i < thread_count_; ++i)
if (assignment_history_[i])
count++;
return count;
}
int WorkQueue::GetNumThreadsCompletingTasks() const {
int count = 0;
for (int i = 0; i < thread_count_; ++i)
if (completion_history_[i])
count++;
return count;
}
int WorkQueue::GetNumberOfCompletedTasks() const {
int total = 0;
for (int i = 0; i < thread_count_; ++i)
total += completion_history_[i];
return total;
}
void WorkQueue::SetWorkTime(TimeDelta delay) {
worker_delay_ = delay;
}
void WorkQueue::SetTaskCount(int count) {
task_count_ = count;
}
void WorkQueue::SetAllowHelp(bool allow) {
allow_help_requests_ = allow;
}
void WorkQueue::SetShutdown() {
shutdown_ = true;
}
} // namespace

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1 @@
This file is different.

@ -0,0 +1 @@
this file is the same.

@ -0,0 +1 @@
This file is the same.

@ -0,0 +1 @@
This file is the same.

@ -0,0 +1 @@
This file is the same.

@ -0,0 +1 @@
This file is not same.

@ -0,0 +1 @@
This file is the

Binary file not shown.

Binary file not shown.

@ -0,0 +1,19 @@
# this test causes Purify to get completely confused, aborting the test and
# popping up 10 or more error dialogs
StatsTableTest.MultipleProcesses
# see bug 1151158
# causes purify to occasionally crash, possibly the same reason as 1110206 below
StatsTableTest.MultipleThreads
# this test takes a really long time to run in Purify
TimeTicks.Rollover
# see bug 1110206
ConditionVariableTest.LargeFastTaskTest
# see bug 1150075
MessageLoopTest.Crasher*
# see bug 1195707
WMIUtilTest.*

@ -0,0 +1,97 @@
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::_Mutex::_Mutex(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::basic_streambuf<char,char_traits<char>::std>::basic_streambuf<char,char_traits<char>::std>(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::ios_base::_Init(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::~LogMessage(void)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::_Mutex::_Mutex(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::basic_streambuf<char,char_traits<char>::std>::basic_streambuf<char,char_traits<char>::std>(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::ios_base::_Init(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::~LogMessage(void)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
CoTaskMemAlloc [OLE32.DLL]
Alloc Location
...
base/wmi_util.cc WMIUtil::CreateLocalConnection(bool)
base/wmi_util.cc WMIProcessUtil::Launch(class std::basic_string const &,int *)
base/wmi_util_unittest.cc WMIUtilTest_TestLaunchProcess_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^

@ -0,0 +1,8 @@
CoTaskMemAlloc [OLE32.DLL]
Alloc Location
...
base/wmi_util.cc WMIUtil::CreateLocalConnection(bool)
base/wmi_util.cc WMIProcessUtil::Launch(class std::basic_string const &,int *)
base/wmi_util_unittest.cc WMIUtilTest_TestLaunchProcess_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^

@ -0,0 +1,93 @@
# -----
# Leaks in ::RaiseException, called when we log a fatal error. See bug 1078612.
std::strstreambuf::overflow(int) [base_unittests.exe]
Alloc Location
...
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::_Mutex::_Mutex(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::basic_streambuf<char,char_traits<char>::std>::basic_streambuf<char,char_traits<char>::std>(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::ios_base::_Init(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::~LogMessage(void)
base/check_handler_unittest.cc ThisFunctionAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckFunc_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::strstreambuf::overflow(int) [base_unittests.exe]
Alloc Location
...
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::_Mutex::_Mutex(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::basic_streambuf<char,char_traits<char>::std>::basic_streambuf<char,char_traits<char>::std>(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::ios_base::_Init(void) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::LogMessage(char const*,int,int)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
std::D::_Allocate(unsigned int,char *) [base_unittests.exe]
Alloc Location
...
base/logging.cc logging::LogMessage::~LogMessage(void)
base/check_handler_unittest.cc SimpleTestClass::ThisMethodAsserts(void)
base/check_handler_unittest.cc CheckHandlerTest_TestMacroCheckObj_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^
# End of leaks in ::RaiseException
# -----

@ -0,0 +1,8 @@
# Probably a Purify error. See bug 1076843.
WideCharToMultiByte: Invalid size (0x27) for destination buffer.
Error Location
...
base/file_util_unittest.cc FileUtilTest_ResolveShortcutTest_Test::TestBody(void)
testing/gtest/src/gtest.cc testing::Test::Run(void)
^^^

Binary file not shown.

After

(image error) Size: 289 B

Binary file not shown.

After

(image error) Size: 289 B

Binary file not shown.

After

(image error) Size: 289 B

Binary file not shown.

After

(image error) Size: 289 B

Binary file not shown.

After

(image error) Size: 537 B

Binary file not shown.

After

(image error) Size: 537 B

Binary file not shown.

After

(image error) Size: 417 B

Binary file not shown.

After

(image error) Size: 417 B

Binary file not shown.

After

(image error) Size: 417 B

Binary file not shown.

After

(image error) Size: 417 B

Binary file not shown.

After

(image error) Size: 433 B

Binary file not shown.

After

(image error) Size: 433 B

Binary file not shown.

After

(image error) Size: 109 B

Binary file not shown.

After

(image error) Size: 109 B

Binary file not shown.

After

(image error) Size: 126 B

Binary file not shown.

After

(image error) Size: 126 B

Binary file not shown.

After

(image error) Size: 271 B

Binary file not shown.

After

(image error) Size: 271 B

Binary file not shown.

After

(image error) Size: 5.0 KiB

Binary file not shown.

After

(image error) Size: 5.0 KiB

Binary file not shown.

After

(image error) Size: 2.6 KiB

Binary file not shown.

After

(image error) Size: 2.6 KiB

Binary file not shown.

After

(image error) Size: 422 B

Binary file not shown.

After

(image error) Size: 3.2 KiB

Binary file not shown.

After

(image error) Size: 383 B

Binary file not shown.

After

(image error) Size: 392 B

Binary file not shown.

After

(image error) Size: 466 B

Binary file not shown.

After

(image error) Size: 460 B

Binary file not shown.

After

(image error) Size: 477 B

Binary file not shown.

After

(image error) Size: 492 B

Binary file not shown.

After

(image error) Size: 568 B

Binary file not shown.

After

(image error) Size: 579 B

Binary file not shown.

After

(image error) Size: 1.1 KiB

Binary file not shown.

After

(image error) Size: 1.2 KiB

Binary file not shown.

After

(image error) Size: 1.3 KiB

Binary file not shown.

After

(image error) Size: 1.3 KiB

Binary file not shown.

After

(image error) Size: 4.6 KiB

Binary file not shown.

After

(image error) Size: 4.6 KiB

Binary file not shown.

After

(image error) Size: 1.3 KiB

Binary file not shown.

After

(image error) Size: 1.3 KiB

Binary file not shown.

After

(image error) Size: 1.2 KiB

Binary file not shown.

After

(image error) Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More