mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1062715 - remove Chromium event recorder, memory debug, simple thread, drag and drop code. rs=bent
This commit is contained in:
parent
19586b7c3c
commit
db6fd5144c
@ -2,8 +2,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/linked_ptr.h"
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
|
||||
|
@ -45,7 +45,6 @@ UNIFIED_SOURCES += [
|
||||
'src/base/lazy_instance.cc',
|
||||
'src/base/lock.cc',
|
||||
'src/base/logging.cc',
|
||||
'src/base/memory_debug.cc',
|
||||
'src/base/message_loop.cc',
|
||||
'src/base/message_pump_default.cc',
|
||||
'src/base/non_thread_safe.cc',
|
||||
@ -54,7 +53,6 @@ UNIFIED_SOURCES += [
|
||||
'src/base/ref_counted.cc',
|
||||
'src/base/revocable_store.cc',
|
||||
'src/base/scoped_temp_dir.cc',
|
||||
'src/base/simple_thread.cc',
|
||||
'src/base/string_piece.cc',
|
||||
'src/base/string_util.cc',
|
||||
'src/base/thread.cc',
|
||||
@ -84,7 +82,6 @@ if os_win:
|
||||
SOURCES += [
|
||||
'src/base/condition_variable_win.cc',
|
||||
'src/base/cpu.cc',
|
||||
'src/base/event_recorder.cc',
|
||||
'src/base/file_util_win.cc',
|
||||
'src/base/idle_timer.cc',
|
||||
'src/base/lock_impl_win.cc',
|
||||
@ -141,7 +138,6 @@ elif not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
if os_posix:
|
||||
SOURCES += [
|
||||
'src/base/condition_variable_posix.cc',
|
||||
'src/base/event_recorder_stubs.cc',
|
||||
'src/base/file_descriptor_shuffle.cc',
|
||||
'src/base/file_util_posix.cc',
|
||||
'src/base/lock_impl_posix.cc',
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#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 // BASE_BASE_DRAG_SOURCE_H_
|
@ -1,130 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_BASE_DROP_TARGET_H_
|
||||
#define BASE_BASE_DROP_TARGET_H_
|
||||
|
||||
#include <objidl.h>
|
||||
|
||||
#include "base/ref_counted.h"
|
||||
|
||||
struct IDropTargetHelper;
|
||||
|
||||
// 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.
|
||||
//
|
||||
// This class is meant to be used in a STA and is not multithread-safe.
|
||||
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);
|
||||
|
||||
// Return the drag identity.
|
||||
static int32_t GetDragIdentity() { return drag_identity_; }
|
||||
|
||||
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.
|
||||
scoped_refptr<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 drag identity (id). An up-counter that increases when the cursor first
|
||||
// moves over the HWND in a DnD session (OnDragEnter). 0 is reserved to mean
|
||||
// the "no/unknown" identity, and is used for initialization. The identity is
|
||||
// sent to the renderer in drag enter notifications. Note: the identity value
|
||||
// is passed over the renderer NPAPI interface to gears, so use int32_t instead
|
||||
// of int here.
|
||||
static int32_t drag_identity_;
|
||||
|
||||
// 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_
|
@ -1,259 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "base/event_recorder.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
// A note about time.
|
||||
// For perfect playback of events, you'd like a very accurate timer
|
||||
// so that events are played back at exactly the same time that
|
||||
// they were recorded. However, windows has a clock which is only
|
||||
// granular to ~15ms. We see more consistent event playback when
|
||||
// using a higher resolution timer. To do this, we use the
|
||||
// timeGetTime API instead of the default GetTickCount() API.
|
||||
|
||||
namespace base {
|
||||
|
||||
EventRecorder* EventRecorder::current_ = NULL;
|
||||
|
||||
LRESULT CALLBACK StaticRecordWndProc(int nCode, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
CHECK(EventRecorder::current());
|
||||
return EventRecorder::current()->RecordWndProc(nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK StaticPlaybackWndProc(int nCode, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
CHECK(EventRecorder::current());
|
||||
return EventRecorder::current()->PlaybackWndProc(nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
EventRecorder::~EventRecorder() {
|
||||
// Try to assert early if the caller deletes the recorder
|
||||
// while it is still in use.
|
||||
DCHECK(!journal_hook_);
|
||||
DCHECK(!is_recording_ && !is_playing_);
|
||||
}
|
||||
|
||||
bool EventRecorder::StartRecording(const FilePath& filename) {
|
||||
if (journal_hook_ != NULL)
|
||||
return false;
|
||||
if (is_recording_ || is_playing_)
|
||||
return false;
|
||||
|
||||
// Open the recording file.
|
||||
DCHECK(file_ == NULL);
|
||||
file_ = file_util::OpenFile(filename, "wb+");
|
||||
if (!file_) {
|
||||
DLOG(ERROR) << "EventRecorder could not open log file";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the faster clock, if possible.
|
||||
::timeBeginPeriod(1);
|
||||
|
||||
// Set the recording hook. JOURNALRECORD can only be used as a global hook.
|
||||
journal_hook_ = ::SetWindowsHookEx(WH_JOURNALRECORD, StaticRecordWndProc,
|
||||
GetModuleHandle(NULL), 0);
|
||||
if (!journal_hook_) {
|
||||
DLOG(ERROR) << "EventRecorder Record Hook failed";
|
||||
file_util::CloseFile(file_);
|
||||
return false;
|
||||
}
|
||||
|
||||
is_recording_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventRecorder::StopRecording() {
|
||||
if (is_recording_) {
|
||||
DCHECK(journal_hook_ != NULL);
|
||||
|
||||
if (!::UnhookWindowsHookEx(journal_hook_)) {
|
||||
DLOG(ERROR) << "EventRecorder Unhook failed";
|
||||
// Nothing else we can really do here.
|
||||
return;
|
||||
}
|
||||
|
||||
::timeEndPeriod(1);
|
||||
|
||||
DCHECK(file_ != NULL);
|
||||
file_util::CloseFile(file_);
|
||||
file_ = NULL;
|
||||
|
||||
journal_hook_ = NULL;
|
||||
is_recording_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventRecorder::StartPlayback(const FilePath& filename) {
|
||||
if (journal_hook_ != NULL)
|
||||
return false;
|
||||
if (is_recording_ || is_playing_)
|
||||
return false;
|
||||
|
||||
// Open the recording file.
|
||||
DCHECK(file_ == NULL);
|
||||
file_ = file_util::OpenFile(filename, "rb");
|
||||
if (!file_) {
|
||||
DLOG(ERROR) << "EventRecorder Playback could not open log file";
|
||||
return false;
|
||||
}
|
||||
// Read the first event from the record.
|
||||
if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1) {
|
||||
DLOG(ERROR) << "EventRecorder Playback has no records!";
|
||||
file_util::CloseFile(file_);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the faster clock, if possible.
|
||||
::timeBeginPeriod(1);
|
||||
|
||||
// Playback time is tricky. When playing back, we read a series of events,
|
||||
// each with timeouts. Simply subtracting the delta between two timers will
|
||||
// lead to fast playback (about 2x speed). The API has two events, one
|
||||
// which advances to the next event (HC_SKIP), and another that requests the
|
||||
// event (HC_GETNEXT). The same event will be requested multiple times.
|
||||
// Each time the event is requested, we must calculate the new delay.
|
||||
// To do this, we track the start time of the playback, and constantly
|
||||
// re-compute the delay. I mention this only because I saw two examples
|
||||
// of how to use this code on the net, and both were broken :-)
|
||||
playback_start_time_ = timeGetTime();
|
||||
playback_first_msg_time_ = playback_msg_.time;
|
||||
|
||||
// Set the hook. JOURNALPLAYBACK can only be used as a global hook.
|
||||
journal_hook_ = ::SetWindowsHookEx(WH_JOURNALPLAYBACK, StaticPlaybackWndProc,
|
||||
GetModuleHandle(NULL), 0);
|
||||
if (!journal_hook_) {
|
||||
DLOG(ERROR) << "EventRecorder Playback Hook failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
is_playing_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventRecorder::StopPlayback() {
|
||||
if (is_playing_) {
|
||||
DCHECK(journal_hook_ != NULL);
|
||||
|
||||
if (!::UnhookWindowsHookEx(journal_hook_)) {
|
||||
DLOG(ERROR) << "EventRecorder Unhook failed";
|
||||
// Nothing else we can really do here.
|
||||
}
|
||||
|
||||
DCHECK(file_ != NULL);
|
||||
file_util::CloseFile(file_);
|
||||
file_ = NULL;
|
||||
|
||||
::timeEndPeriod(1);
|
||||
|
||||
journal_hook_ = NULL;
|
||||
is_playing_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Windows callback hook for the recorder.
|
||||
LRESULT EventRecorder::RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
static bool recording_enabled = true;
|
||||
EVENTMSG* msg_ptr = NULL;
|
||||
|
||||
// The API says we have to do this.
|
||||
// See http://msdn2.microsoft.com/en-us/library/ms644983(VS.85).aspx
|
||||
if (nCode < 0)
|
||||
return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);
|
||||
|
||||
// Check for the break key being pressed and stop recording.
|
||||
if (::GetKeyState(VK_CANCEL) & 0x8000) {
|
||||
StopRecording();
|
||||
return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
// The Journal Recorder must stop recording events when system modal
|
||||
// dialogs are present. (see msdn link above)
|
||||
switch(nCode) {
|
||||
case HC_SYSMODALON:
|
||||
recording_enabled = false;
|
||||
break;
|
||||
case HC_SYSMODALOFF:
|
||||
recording_enabled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nCode == HC_ACTION && recording_enabled) {
|
||||
// Aha - we have an event to record.
|
||||
msg_ptr = reinterpret_cast<EVENTMSG*>(lParam);
|
||||
msg_ptr->time = timeGetTime();
|
||||
fwrite(msg_ptr, sizeof(EVENTMSG), 1, file_);
|
||||
fflush(file_);
|
||||
}
|
||||
|
||||
return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
// Windows callback for the playback mode.
|
||||
LRESULT EventRecorder::PlaybackWndProc(int nCode, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
static bool playback_enabled = true;
|
||||
int delay = 0;
|
||||
|
||||
switch(nCode) {
|
||||
// A system modal dialog box is being displayed. Stop playing back
|
||||
// messages.
|
||||
case HC_SYSMODALON:
|
||||
playback_enabled = false;
|
||||
break;
|
||||
|
||||
// A system modal dialog box is destroyed. We can start playing back
|
||||
// messages again.
|
||||
case HC_SYSMODALOFF:
|
||||
playback_enabled = true;
|
||||
break;
|
||||
|
||||
// Prepare to copy the next mouse or keyboard event to playback.
|
||||
case HC_SKIP:
|
||||
if (!playback_enabled)
|
||||
break;
|
||||
|
||||
// Read the next event from the record.
|
||||
if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1)
|
||||
this->StopPlayback();
|
||||
break;
|
||||
|
||||
// Copy the mouse or keyboard event to the EVENTMSG structure in lParam.
|
||||
case HC_GETNEXT:
|
||||
if (!playback_enabled)
|
||||
break;
|
||||
|
||||
memcpy(reinterpret_cast<void*>(lParam), &playback_msg_,
|
||||
sizeof(playback_msg_));
|
||||
|
||||
// The return value is the amount of time (in milliseconds) to wait
|
||||
// before playing back the next message in the playback queue. Each
|
||||
// time this is called, we recalculate the delay relative to our current
|
||||
// wall clock.
|
||||
delay = (playback_msg_.time - playback_first_msg_time_) -
|
||||
(timeGetTime() - playback_start_time_);
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
return delay;
|
||||
|
||||
// An application has called PeekMessage with wRemoveMsg set to PM_NOREMOVE
|
||||
// indicating that the message is not removed from the message queue after
|
||||
// PeekMessage processing.
|
||||
case HC_NOREMOVE:
|
||||
break;
|
||||
}
|
||||
|
||||
return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
} // namespace base
|
@ -1,102 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_EVENT_RECORDER_H_
|
||||
#define BASE_EVENT_RECORDER_H_
|
||||
|
||||
#include <string>
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "base/basictypes.h"
|
||||
|
||||
class FilePath;
|
||||
|
||||
namespace base {
|
||||
|
||||
// A class for recording and playing back keyboard and mouse input events.
|
||||
//
|
||||
// Note - if you record events, and the playback with the windows in
|
||||
// different sizes or positions, the playback will fail. When
|
||||
// recording and playing, you should move the relevant windows
|
||||
// to constant sizes and locations.
|
||||
// TODO(mbelshe) For now this is a singleton. I believe that this class
|
||||
// could be easily modified to:
|
||||
// support two simultaneous recorders
|
||||
// be playing back events while already recording events.
|
||||
// Why? Imagine if the product had a "record a macro" feature.
|
||||
// You might be recording globally, while recording or playing back
|
||||
// a macro. I don't think two playbacks make sense.
|
||||
class EventRecorder {
|
||||
public:
|
||||
// Get the singleton EventRecorder.
|
||||
// We can only handle one recorder/player at a time.
|
||||
static EventRecorder* current() {
|
||||
if (!current_)
|
||||
current_ = new EventRecorder();
|
||||
return current_;
|
||||
}
|
||||
|
||||
// Starts recording events.
|
||||
// Will clobber the file if it already exists.
|
||||
// Returns true on success, or false if an error occurred.
|
||||
bool StartRecording(const FilePath& filename);
|
||||
|
||||
// Stops recording.
|
||||
void StopRecording();
|
||||
|
||||
// Is the EventRecorder currently recording.
|
||||
bool is_recording() const { return is_recording_; }
|
||||
|
||||
// Plays events previously recorded.
|
||||
// Returns true on success, or false if an error occurred.
|
||||
bool StartPlayback(const FilePath& filename);
|
||||
|
||||
// Stops playback.
|
||||
void StopPlayback();
|
||||
|
||||
// Is the EventRecorder currently playing.
|
||||
bool is_playing() const { return is_playing_; }
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// C-style callbacks for the EventRecorder.
|
||||
// Used for internal purposes only.
|
||||
LRESULT RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT PlaybackWndProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Create a new EventRecorder. Events are saved to the file filename.
|
||||
// If the file already exists, it will be deleted before recording
|
||||
// starts.
|
||||
explicit EventRecorder()
|
||||
: is_recording_(false),
|
||||
is_playing_(false),
|
||||
#if defined(OS_WIN)
|
||||
journal_hook_(NULL),
|
||||
file_(NULL),
|
||||
#endif
|
||||
playback_first_msg_time_(0),
|
||||
playback_start_time_(0) {
|
||||
}
|
||||
~EventRecorder();
|
||||
|
||||
static EventRecorder* current_; // Our singleton.
|
||||
|
||||
bool is_recording_;
|
||||
bool is_playing_;
|
||||
#if defined(OS_WIN)
|
||||
HHOOK journal_hook_;
|
||||
FILE* file_;
|
||||
EVENTMSG playback_msg_;
|
||||
#endif
|
||||
int playback_first_msg_time_;
|
||||
int playback_start_time_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(EventRecorder);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_EVENT_RECORDER_H_
|
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/event_recorder.h"
|
||||
|
||||
// This file implements a link stub for EventRecorder that can be used on
|
||||
// platforms that don't have a working EventRecorder implementation.
|
||||
|
||||
namespace base {
|
||||
|
||||
EventRecorder* EventRecorder::current_; // Our singleton.
|
||||
|
||||
bool EventRecorder::StartRecording(const FilePath& filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventRecorder::StopRecording() {
|
||||
}
|
||||
|
||||
bool EventRecorder::StartPlayback(const FilePath& filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventRecorder::StopPlayback() {
|
||||
}
|
||||
|
||||
} // namespace
|
@ -1,54 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/memory_debug.h"
|
||||
|
||||
#ifdef PURIFY
|
||||
// this #define is used to prevent people from directly using pure.h
|
||||
// instead of memory_debug.h
|
||||
#define PURIFY_PRIVATE_INCLUDE
|
||||
#include "base/third_party/purify/pure.h"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
|
||||
bool MemoryDebug::memory_in_use_ = false;
|
||||
|
||||
void MemoryDebug::SetMemoryInUseEnabled(bool enabled) {
|
||||
memory_in_use_ = enabled;
|
||||
}
|
||||
|
||||
void MemoryDebug::DumpAllMemoryInUse() {
|
||||
#ifdef PURIFY
|
||||
if (memory_in_use_)
|
||||
PurifyAllInuse();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryDebug::DumpNewMemoryInUse() {
|
||||
#ifdef PURIFY
|
||||
if (memory_in_use_)
|
||||
PurifyNewInuse();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryDebug::DumpAllLeaks() {
|
||||
#ifdef PURIFY
|
||||
PurifyAllLeaks();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryDebug::DumpNewLeaks() {
|
||||
#ifdef PURIFY
|
||||
PurifyNewLeaks();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryDebug::MarkAsInitialized(void* addr, size_t size) {
|
||||
#ifdef PURIFY
|
||||
PurifyMarkAsInitialized(addr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace base
|
@ -1,46 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Functions used to debug memory usage, leaks, and other memory issues.
|
||||
// All methods are effectively no-ops unless this program is being run through
|
||||
// a supported memory tool (currently, only Purify)
|
||||
|
||||
#ifndef BASE_MEMORY_DEBUG_H_
|
||||
#define BASE_MEMORY_DEBUG_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class MemoryDebug {
|
||||
public:
|
||||
// Since MIU messages are a lot of data, and we don't always want this data,
|
||||
// we have a global switch. If disabled, *MemoryInUse are no-ops.
|
||||
static void SetMemoryInUseEnabled(bool enabled);
|
||||
|
||||
// Dump information about all memory in use.
|
||||
static void DumpAllMemoryInUse();
|
||||
// Dump information about new memory in use since the last
|
||||
// call to DumpAllMemoryInUse() or DumpNewMemoryInUse().
|
||||
static void DumpNewMemoryInUse();
|
||||
|
||||
// Dump information about all current memory leaks.
|
||||
static void DumpAllLeaks();
|
||||
// Dump information about new memory leaks since the last
|
||||
// call to DumpAllLeaks() or DumpNewLeaks()
|
||||
static void DumpNewLeaks();
|
||||
|
||||
// Mark |size| bytes of memory as initialized, so it doesn't produce any UMRs
|
||||
// or UMCs.
|
||||
static void MarkAsInitialized(void* addr, size_t size);
|
||||
|
||||
private:
|
||||
static bool memory_in_use_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryDebug);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_MEMORY_DEBUG_H_
|
@ -1,118 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/simple_thread.h"
|
||||
|
||||
#include "base/waitable_event.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/platform_thread.h"
|
||||
#include "base/string_util.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
void SimpleThread::Start() {
|
||||
DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times.";
|
||||
bool success = PlatformThread::Create(options_.stack_size(), this, &thread_);
|
||||
CHECK(success);
|
||||
event_.Wait(); // Wait for the thread to complete initialization.
|
||||
}
|
||||
|
||||
void SimpleThread::Join() {
|
||||
DCHECK(HasBeenStarted()) << "Tried to Join a never-started thread.";
|
||||
DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times.";
|
||||
PlatformThread::Join(thread_);
|
||||
joined_ = true;
|
||||
}
|
||||
|
||||
void SimpleThread::ThreadMain() {
|
||||
tid_ = PlatformThread::CurrentId();
|
||||
// Construct our full name of the form "name_prefix_/TID".
|
||||
name_.push_back('/');
|
||||
name_.append(IntToString(tid_));
|
||||
PlatformThread::SetName(name_.c_str());
|
||||
|
||||
// We've initialized our new thread, signal that we're done to Start().
|
||||
event_.Signal();
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
SimpleThread::~SimpleThread() {
|
||||
DCHECK(HasBeenStarted()) << "SimpleThread was never started.";
|
||||
DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed.";
|
||||
}
|
||||
|
||||
void DelegateSimpleThread::Run() {
|
||||
DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)";
|
||||
delegate_->Run();
|
||||
delegate_ = NULL;
|
||||
}
|
||||
|
||||
DelegateSimpleThreadPool::~DelegateSimpleThreadPool() {
|
||||
DCHECK(threads_.empty());
|
||||
DCHECK(delegates_.empty());
|
||||
DCHECK(!dry_.IsSignaled());
|
||||
}
|
||||
|
||||
void DelegateSimpleThreadPool::Start() {
|
||||
DCHECK(threads_.empty()) << "Start() called with outstanding threads.";
|
||||
for (int i = 0; i < num_threads_; ++i) {
|
||||
DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_);
|
||||
thread->Start();
|
||||
threads_.push_back(thread);
|
||||
}
|
||||
}
|
||||
|
||||
void DelegateSimpleThreadPool::JoinAll() {
|
||||
DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads.";
|
||||
|
||||
// Tell all our threads to quit their worker loop.
|
||||
AddWork(NULL, num_threads_);
|
||||
|
||||
// Join and destroy all the worker threads.
|
||||
for (int i = 0; i < num_threads_; ++i) {
|
||||
threads_[i]->Join();
|
||||
delete threads_[i];
|
||||
}
|
||||
threads_.clear();
|
||||
DCHECK(delegates_.empty());
|
||||
}
|
||||
|
||||
void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) {
|
||||
AutoLock locked(lock_);
|
||||
for (int i = 0; i < repeat_count; ++i)
|
||||
delegates_.push(delegate);
|
||||
// If we were empty, signal that we have work now.
|
||||
if (!dry_.IsSignaled())
|
||||
dry_.Signal();
|
||||
}
|
||||
|
||||
void DelegateSimpleThreadPool::Run() {
|
||||
Delegate* work;
|
||||
|
||||
while (true) {
|
||||
dry_.Wait();
|
||||
{
|
||||
AutoLock locked(lock_);
|
||||
if (!dry_.IsSignaled())
|
||||
continue;
|
||||
|
||||
DCHECK(!delegates_.empty());
|
||||
work = delegates_.front();
|
||||
delegates_.pop();
|
||||
|
||||
// Signal to any other threads that we're currently out of work.
|
||||
if (delegates_.empty())
|
||||
dry_.Reset();
|
||||
}
|
||||
|
||||
// A NULL delegate pointer signals us to quit.
|
||||
if (!work)
|
||||
break;
|
||||
|
||||
work->Run();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace base
|
@ -1,189 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// WARNING: You should probably be using Thread (thread.h) instead. Thread is
|
||||
// Chrome's message-loop based Thread abstraction, and if you are a
|
||||
// thread running in the browser, there will likely be assumptions
|
||||
// that your thread will have an associated message loop.
|
||||
//
|
||||
// This is a simple thread interface that backs to a native operating system
|
||||
// thread. You should use this only when you want a thread that does not have
|
||||
// an associated MessageLoop. Unittesting is the best example of this.
|
||||
//
|
||||
// The simplest interface to use is DelegateSimpleThread, which will create
|
||||
// a new thread, and execute the Delegate's virtual Run() in this new thread
|
||||
// until it has completed, exiting the thread.
|
||||
//
|
||||
// NOTE: You *MUST* call Join on the thread to clean up the underlying thread
|
||||
// resources. You are also responsible for destructing the SimpleThread object.
|
||||
// It is invalid to destroy a SimpleThread while it is running, or without
|
||||
// Start() having been called (and a thread never created). The Delegate
|
||||
// object should live as long as a DelegateSimpleThread.
|
||||
//
|
||||
// Thread Safety: A SimpleThread is not completely thread safe. It is safe to
|
||||
// access it from the creating thread or from the newly created thread. This
|
||||
// implies that the creator thread should be the thread that calls Join.
|
||||
//
|
||||
// Example:
|
||||
// class MyThreadRunner : public DelegateSimpleThread::Delegate { ... };
|
||||
// MyThreadRunner runner;
|
||||
// DelegateSimpleThread thread(&runner, "good_name_here");
|
||||
// thread.Start();
|
||||
// // Start will return after the Thread has been successfully started and
|
||||
// // initialized. The newly created thread will invoke runner->Run(), and
|
||||
// // run until it returns.
|
||||
// thread.Join(); // Wait until the thread has exited. You *MUST* Join!
|
||||
// // The SimpleThread object is still valid, however you may not call Join
|
||||
// // or Start again.
|
||||
|
||||
#ifndef BASE_SIMPLE_THREAD_H_
|
||||
#define BASE_SIMPLE_THREAD_H_
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/waitable_event.h"
|
||||
#include "base/platform_thread.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// This is the base SimpleThread. You can derive from it and implement the
|
||||
// virtual Run method, or you can use the DelegateSimpleThread interface.
|
||||
class SimpleThread : public PlatformThread::Delegate {
|
||||
public:
|
||||
class Options {
|
||||
public:
|
||||
Options() : stack_size_(0) { }
|
||||
~Options() { }
|
||||
|
||||
// We use the standard compiler-supplied copy constructor.
|
||||
|
||||
// A custom stack size, or 0 for the system default.
|
||||
void set_stack_size(size_t size) { stack_size_ = size; }
|
||||
size_t stack_size() const { return stack_size_; }
|
||||
private:
|
||||
size_t stack_size_;
|
||||
};
|
||||
|
||||
// Create a SimpleThread. |options| should be used to manage any specific
|
||||
// configuration involving the thread creation and management.
|
||||
// Every thread has a name, in the form of |name_prefix|/TID, for example
|
||||
// "my_thread/321". The thread will not be created until Start() is called.
|
||||
explicit SimpleThread(const std::string& name_prefix)
|
||||
: name_prefix_(name_prefix), name_(name_prefix),
|
||||
thread_(), event_(true, false), tid_(0), joined_(false) { }
|
||||
SimpleThread(const std::string& name_prefix, const Options& options)
|
||||
: name_prefix_(name_prefix), name_(name_prefix), options_(options),
|
||||
thread_(), event_(true, false), tid_(0), joined_(false) { }
|
||||
|
||||
virtual ~SimpleThread();
|
||||
|
||||
virtual void Start();
|
||||
virtual void Join();
|
||||
|
||||
// We follow the PlatformThread Delegate interface.
|
||||
virtual void ThreadMain();
|
||||
|
||||
// Subclasses should override the Run method.
|
||||
virtual void Run() = 0;
|
||||
|
||||
// Return the thread name prefix, or "unnamed" if none was supplied.
|
||||
std::string name_prefix() { return name_prefix_; }
|
||||
|
||||
// Return the completed name including TID, only valid after Start().
|
||||
std::string name() { return name_; }
|
||||
|
||||
// Return the thread id, only valid after Start().
|
||||
PlatformThreadId tid() { return tid_; }
|
||||
|
||||
// Return True if Start() has ever been called.
|
||||
bool HasBeenStarted() { return event_.IsSignaled(); }
|
||||
|
||||
// Return True if Join() has evern been called.
|
||||
bool HasBeenJoined() { return joined_; }
|
||||
|
||||
private:
|
||||
const std::string name_prefix_;
|
||||
std::string name_;
|
||||
const Options options_;
|
||||
PlatformThreadHandle thread_; // PlatformThread handle, invalid after Join!
|
||||
WaitableEvent event_; // Signaled if Start() was ever called.
|
||||
PlatformThreadId tid_; // The backing thread's id.
|
||||
bool joined_; // True if Join has been called.
|
||||
};
|
||||
|
||||
class DelegateSimpleThread : public SimpleThread {
|
||||
public:
|
||||
class Delegate {
|
||||
public:
|
||||
Delegate() { }
|
||||
virtual ~Delegate() { }
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
DelegateSimpleThread(Delegate* delegate,
|
||||
const std::string& name_prefix)
|
||||
: SimpleThread(name_prefix), delegate_(delegate) { }
|
||||
DelegateSimpleThread(Delegate* delegate,
|
||||
const std::string& name_prefix,
|
||||
const Options& options)
|
||||
: SimpleThread(name_prefix, options), delegate_(delegate) { }
|
||||
|
||||
virtual ~DelegateSimpleThread() { }
|
||||
virtual void Run();
|
||||
private:
|
||||
Delegate* delegate_;
|
||||
};
|
||||
|
||||
// DelegateSimpleThreadPool allows you to start up a fixed number of threads,
|
||||
// and then add jobs which will be dispatched to the threads. This is
|
||||
// convenient when you have a lot of small work that you want done
|
||||
// multi-threaded, but don't want to spawn a thread for each small bit of work.
|
||||
//
|
||||
// You just call AddWork() to add a delegate to the list of work to be done.
|
||||
// JoinAll() will make sure that all outstanding work is processed, and wait
|
||||
// for everything to finish. You can reuse a pool, so you can call Start()
|
||||
// again after you've called JoinAll().
|
||||
class DelegateSimpleThreadPool : public DelegateSimpleThread::Delegate {
|
||||
public:
|
||||
typedef DelegateSimpleThread::Delegate Delegate;
|
||||
|
||||
DelegateSimpleThreadPool(const std::string name_prefix, int num_threads)
|
||||
: name_prefix_(name_prefix), num_threads_(num_threads),
|
||||
dry_(true, false) { }
|
||||
~DelegateSimpleThreadPool();
|
||||
|
||||
// Start up all of the underlying threads, and start processing work if we
|
||||
// have any.
|
||||
void Start();
|
||||
|
||||
// Make sure all outstanding work is finished, and wait for and destroy all
|
||||
// of the underlying threads in the pool.
|
||||
void JoinAll();
|
||||
|
||||
// It is safe to AddWork() any time, before or after Start().
|
||||
// Delegate* should always be a valid pointer, NULL is reserved internally.
|
||||
void AddWork(Delegate* work, int repeat_count);
|
||||
void AddWork(Delegate* work) {
|
||||
AddWork(work, 1);
|
||||
}
|
||||
|
||||
// We implement the Delegate interface, for running our internal threads.
|
||||
virtual void Run();
|
||||
|
||||
private:
|
||||
const std::string name_prefix_;
|
||||
int num_threads_;
|
||||
std::vector<DelegateSimpleThread*> threads_;
|
||||
std::queue<Delegate*> delegates_;
|
||||
Lock lock_; // Locks delegates_
|
||||
WaitableEvent dry_; // Not signaled when there is no work to do.
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_SIMPLE_THREAD_H_
|
Loading…
Reference in New Issue
Block a user