<commit_before>//
// Name:	 canvas.cpp
// Purpose: Implements the canvas class for the Enviro wxWidgets application.
//
// Copyright (c) 2001-2006 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Event.h"
#include "vtdata/vtLog.h"
#include "EnviroGUI.h"			// for g_App, GetTerrainScene
#include "canvas.h"
#include "EnviroFrame.h"		// for UpdateStatus and OnChar
#include "EnviroApp.h"

DECLARE_APP(EnviroApp)

/*
 * vtGLCanvas implementation
 */
BEGIN_EVENT_TABLE(vtGLCanvas, wxGLCanvas)
EVT_CLOSE(vtGLCanvas::OnClose)
EVT_SIZE(vtGLCanvas::OnSize)
EVT_PAINT(vtGLCanvas::OnPaint)
EVT_CHAR(vtGLCanvas::OnChar)
EVT_KEY_DOWN(vtGLCanvas::OnKeyDown)
EVT_KEY_UP(vtGLCanvas::OnKeyUp)
EVT_MOUSE_EVENTS(vtGLCanvas::OnMouseEvent)
EVT_ERASE_BACKGROUND(vtGLCanvas::OnEraseBackground)
EVT_IDLE(vtGLCanvas::OnIdle)
END_EVENT_TABLE()

static vtGLCanvas *s_canvas = NULL;

vtGLCanvas::vtGLCanvas(wxWindow *parent, wxWindowID id, const wxPoint &pos,
	const wxSize &size, long style, const wxString &name, int *gl_attrib):
		wxGLCanvas(parent, id, gl_attrib, pos, size, style, name)
{
	VTLOG1("vtGLCanvas constructor\n");

	VTLOG1("vtGLCanvas: calling Show on parent\n");
	parent->Show();

	m_glContext = new wxGLContext(this);

#if __WXMSW__
	HGLRC hContext = m_glContext->GetGLRC();
	if (NULL == hContext)
	{
		wxMessageBox(_("No OpenGL support found") , _("Error"), wxICON_ERROR | wxOK);
		exit(-1);
	}
	else
		VTLOG("OpenGL context: %lx\n", hContext);
#endif

	// Documentation says about SetCurrent:
	// "Note that this function may only be called after the window has been shown."
	VTLOG1("vtGLCanvas: calling SetCurrent\n");
	SetCurrent();

	VTLOG1("OpenGL version: ");
	VTLOG1((const char *) glGetString(GL_VERSION));
	VTLOG1("\n");
	VTLOG1("OpenGL vendor: ");
	VTLOG1((const char *) glGetString(GL_VENDOR));
	VTLOG1("\n");
	VTLOG1("OpenGL renderer: ");
	VTLOG1((const char *) glGetString(GL_RENDERER));
	VTLOG1("\n");

	m_bPainting = false;
	m_bRunning = true;
	m_bShowFrameRateChart = false;

	for (int i = 0; i < 512; i++)
		m_pbKeyState[i] = false;
	vtGetScene()->SetKeyStates(m_pbKeyState);
	m_iConsecutiveMousemoves = 0;

	// On RTL (right-to-left) system, the canvas should still be always LTR
	SetLayoutDirection(wxLayout_LeftToRight);

	s_canvas = this;
	VTLOG1("vtGLCanvas, leaving constructor\n");
}

vtGLCanvas::~vtGLCanvas(void)
{
	VTLOG1("Deleting Canvas\n");
}

void EnableContinuousRendering(bool bTrue)
{
	VTLOG("EnableContinuousRendering %d\n", bTrue);
	if (!s_canvas)
		return;

	bool bNeedRefresh = (s_canvas->m_bRunning == false && bTrue == true);
	s_canvas->m_bRunning = bTrue;
	if (bNeedRefresh)
		s_canvas->Refresh(FALSE);

	vtGetScene()->TimerRunning(bTrue);
}

void vtGLCanvas::OnPaint( wxPaintEvent& event )
{
	static bool bFirstPaint = true;
	if (bFirstPaint) VTLOG1("vtGLCanvas: first OnPaint\n");

	// place the dc inside a scope, to delete it before the end of function
	if (1)
	{
		// This is a dummy, to avoid an endless succession of paint messages.
		// OnPaint handlers must always create a wxPaintDC.
		if (bFirstPaint) VTLOG1("vtGLCanvas: creating a wxPaintDC on the stack\n");
		wxPaintDC dc(this);

		// Safety checks
		if (!s_canvas)
		{
			VTLOG1("OnPaint: Canvas not yet constructed, returning\n");
			return;
		}

		// Avoid reentrance
		if (m_bPainting) return;

		m_bPainting = true;

		// Make sure the Graphics context of this thread is this window
		SetCurrent();

		// Render the Scene Graph
		if (bFirstPaint) VTLOG1("vtGLCanvas: DoUpdate\n");
		vtGetScene()->DoUpdate();

		if (m_bShowFrameRateChart)
			vtGetScene()->DrawFrameRateChart();

		if (bFirstPaint) VTLOG1("vtGLCanvas: SwapBuffers\n");
		SwapBuffers();

		if (bFirstPaint) VTLOG1("vtGLCanvas: update status bar\n");
		EnviroFrame *frame = (EnviroFrame*) GetParent();

		// update the status bar every 1/10 of a second
		static float last_stat = 0.0f;
		static vtString last_msg;
		float cur = vtGetTime();
		if (cur - last_stat > 0.1f || g_App.GetMessage() != last_msg)
		{
			last_msg = g_App.GetMessage();
			last_stat = cur;
			frame->UpdateStatus();
		}

		frame->UpdateLODInfo();

		m_bPainting = false;
	}

	// Reset the number of mousemoves we've gotten since last redraw
	m_iConsecutiveMousemoves = 0;

	if (bFirstPaint)
		bFirstPaint = false;
}

void vtGLCanvas::OnClose(wxCloseEvent& event)
{
	m_bRunning = false;
}

void vtGLCanvas::OnSize(wxSizeEvent& event)
{
	static int count = 0;
	if (count < 3)
	{
		VTLOG("Canvas  OnSize: %d %d\n", event.GetSize().x, event.GetSize().y);
		count++;
	}
	SetCurrent();
	int width, height;
	GetClientSize(& width, & height);

	vtGetScene()->SetWindowSize(width, height);

	wxGLCanvas::OnSize(event);
}

void vtGLCanvas::OnChar(wxKeyEvent& event)
{
	long key = event.GetKeyCode();

	// pass the char to the frame for it to do "accelerator" shortcuts
	EnviroFrame *frame = (EnviroFrame*) GetParent();
	frame->OnChar(event);

	int flags = 0;

	if (event.ControlDown())
		flags |= VT_CONTROL;

	if (event.ShiftDown())
		flags |= VT_SHIFT;

	if (event.AltDown())
		flags |= VT_ALT;

	// pass the char to the vtlib Scene
	vtGetScene()->OnKey(key, flags);

	// Allow wxWindows to pass the event along to other code
	event.Skip();
}

void vtGLCanvas::OnKeyDown(wxKeyEvent& event)
{
	m_pbKeyState[event.m_keyCode] = true;
	event.Skip();
}

void vtGLCanvas::OnKeyUp(wxKeyEvent& event)
{
	m_pbKeyState[event.m_keyCode] = false;
	event.Skip();
}

void vtGLCanvas::OnMouseEvent(wxMouseEvent& event1)
{
	static bool bCapture = false;

	// turn WX mouse event into a VT mouse event
	vtMouseEvent event;
	wxEventType  ev = event1.GetEventType();
	if (ev == wxEVT_LEFT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_LEFT_UP) {
		event.type = VT_UP;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_MIDDLE_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_MIDDLE_UP) {
		event.type = VT_UP;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_RIGHT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_RIGHT_UP) {
		event.type = VT_UP;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_MOTION) {
		event.type = VT_MOVE;
		event.button = VT_NONE;
		m_iConsecutiveMousemoves++;		// Increment
	} else if (ev == wxEVT_MOUSEWHEEL) {
		event.type = VT_WHEEL;
		event.button = event1.GetWheelRotation() / event1.GetWheelDelta();
	} else {
		// ignored mouse events, such as wxEVT_LEAVE_WINDOW
		return;
	}

	if (ev == wxEVT_LEFT_DOWN || ev == wxEVT_MIDDLE_DOWN || ev == wxEVT_RIGHT_DOWN)
	{
//		VTLOG("DOWN: capture %d", bCapture);
		if (!bCapture)
		{
			CaptureMouse();
			bCapture = true;
//			VTLOG(" -> true");
		}
//		VTLOG("\n");
	}
	if (ev == wxEVT_LEFT_UP || ev == wxEVT_MIDDLE_UP || ev == wxEVT_RIGHT_UP)
	{
//		VTLOG("  UP: capture %d", bCapture);
		if (bCapture)
		{
			ReleaseMouse();
			bCapture = false;
//			VTLOG(" -> false");
		}
//		VTLOG("\n");
	}

	// Because of the way the event pump works, if it takes too long to
	//  handle a MouseMove event, then we might get the next MouseMove
	//  event without ever seeing a Redraw or Idle.  That's because the
	//  MouseMove events are considered higher priority in the queue.
	// So, to keep Enviro response smooth, we effectively ignore all but
	//  one MouseMove event per Draw event.
	if (ev == wxEVT_MOTION && m_iConsecutiveMousemoves > 1)
		return;

	event.flags = 0;
	wxCoord xpos, ypos;
	event1.GetPosition(&xpos, &ypos);
	event.pos.Set(xpos, ypos);

	if (event1.ControlDown())
		event.flags |= VT_CONTROL;

	if (event1.ShiftDown())
		event.flags |= VT_SHIFT;

	if (event1.AltDown())
		event.flags |= VT_ALT;

	// inform vtlib scene, which informs the engines
	vtGetScene()->OnMouse(event);

	// inform Enviro app
	g_App.OnMouse(event);
}

void vtGLCanvas::OnEraseBackground(wxEraseEvent& event)
{
	// Do nothing, to avoid flashing.
}

void vtGLCanvas::OnIdle(wxIdleEvent &event)
{
	// We use the "Refresh on Idle" approach to continuous rendering.
	if (m_bRunning)
		Refresh(FALSE);
}

<commit_msg>used older wx API for __WXMAC__<commit_after>//
// Name:	 canvas.cpp
// Purpose: Implements the canvas class for the Enviro wxWidgets application.
//
// Copyright (c) 2001-2006 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Event.h"
#include "vtdata/vtLog.h"
#include "EnviroGUI.h"			// for g_App, GetTerrainScene
#include "canvas.h"
#include "EnviroFrame.h"		// for UpdateStatus and OnChar
#include "EnviroApp.h"

DECLARE_APP(EnviroApp)

/*
 * vtGLCanvas implementation
 */
BEGIN_EVENT_TABLE(vtGLCanvas, wxGLCanvas)
EVT_CLOSE(vtGLCanvas::OnClose)
EVT_SIZE(vtGLCanvas::OnSize)
EVT_PAINT(vtGLCanvas::OnPaint)
EVT_CHAR(vtGLCanvas::OnChar)
EVT_KEY_DOWN(vtGLCanvas::OnKeyDown)
EVT_KEY_UP(vtGLCanvas::OnKeyUp)
EVT_MOUSE_EVENTS(vtGLCanvas::OnMouseEvent)
EVT_ERASE_BACKGROUND(vtGLCanvas::OnEraseBackground)
EVT_IDLE(vtGLCanvas::OnIdle)
END_EVENT_TABLE()

static vtGLCanvas *s_canvas = NULL;

vtGLCanvas::vtGLCanvas(wxWindow *parent, wxWindowID id, const wxPoint &pos,
	const wxSize &size, long style, const wxString &name, int *gl_attrib):
#ifdef __WXMAC__
		wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
#else
		wxGLCanvas(parent, id, gl_attrib, pos, size, style, name)
#endif
{
	VTLOG1("vtGLCanvas constructor\n");

	VTLOG1("vtGLCanvas: calling Show on parent\n");
	parent->Show();

#ifndef __WXMAC__
	m_glContext = new wxGLContext(this);
#endif

#if __WXMSW__
	HGLRC hContext = m_glContext->GetGLRC();
	if (NULL == hContext)
	{
		wxMessageBox(_("No OpenGL support found") , _("Error"), wxICON_ERROR | wxOK);
		exit(-1);
	}
	else
		VTLOG("OpenGL context: %lx\n", hContext);
#endif

	// Documentation says about SetCurrent:
	// "Note that this function may only be called after the window has been shown."
	VTLOG1("vtGLCanvas: calling SetCurrent\n");
	SetCurrent();

	VTLOG1("OpenGL version: ");
	VTLOG1((const char *) glGetString(GL_VERSION));
	VTLOG1("\n");
	VTLOG1("OpenGL vendor: ");
	VTLOG1((const char *) glGetString(GL_VENDOR));
	VTLOG1("\n");
	VTLOG1("OpenGL renderer: ");
	VTLOG1((const char *) glGetString(GL_RENDERER));
	VTLOG1("\n");

	m_bPainting = false;
	m_bRunning = true;
	m_bShowFrameRateChart = false;

	for (int i = 0; i < 512; i++)
		m_pbKeyState[i] = false;
	vtGetScene()->SetKeyStates(m_pbKeyState);
	m_iConsecutiveMousemoves = 0;

	// On RTL (right-to-left) system, the canvas should still be always LTR
	SetLayoutDirection(wxLayout_LeftToRight);

	s_canvas = this;
	VTLOG1("vtGLCanvas, leaving constructor\n");
}

vtGLCanvas::~vtGLCanvas(void)
{
	VTLOG1("Deleting Canvas\n");
}

void EnableContinuousRendering(bool bTrue)
{
	VTLOG("EnableContinuousRendering %d\n", bTrue);
	if (!s_canvas)
		return;

	bool bNeedRefresh = (s_canvas->m_bRunning == false && bTrue == true);
	s_canvas->m_bRunning = bTrue;
	if (bNeedRefresh)
		s_canvas->Refresh(FALSE);

	vtGetScene()->TimerRunning(bTrue);
}

void vtGLCanvas::OnPaint( wxPaintEvent& event )
{
	static bool bFirstPaint = true;
	if (bFirstPaint) VTLOG1("vtGLCanvas: first OnPaint\n");

	// place the dc inside a scope, to delete it before the end of function
	if (1)
	{
		// This is a dummy, to avoid an endless succession of paint messages.
		// OnPaint handlers must always create a wxPaintDC.
		if (bFirstPaint) VTLOG1("vtGLCanvas: creating a wxPaintDC on the stack\n");
		wxPaintDC dc(this);

		// Safety checks
		if (!s_canvas)
		{
			VTLOG1("OnPaint: Canvas not yet constructed, returning\n");
			return;
		}

		// Avoid reentrance
		if (m_bPainting) return;

		m_bPainting = true;

		// Make sure the Graphics context of this thread is this window
		SetCurrent();

		// Render the Scene Graph
		if (bFirstPaint) VTLOG1("vtGLCanvas: DoUpdate\n");
		vtGetScene()->DoUpdate();

		if (m_bShowFrameRateChart)
			vtGetScene()->DrawFrameRateChart();

		if (bFirstPaint) VTLOG1("vtGLCanvas: SwapBuffers\n");
		SwapBuffers();

		if (bFirstPaint) VTLOG1("vtGLCanvas: update status bar\n");
		EnviroFrame *frame = (EnviroFrame*) GetParent();

		// update the status bar every 1/10 of a second
		static float last_stat = 0.0f;
		static vtString last_msg;
		float cur = vtGetTime();
		if (cur - last_stat > 0.1f || g_App.GetMessage() != last_msg)
		{
			last_msg = g_App.GetMessage();
			last_stat = cur;
			frame->UpdateStatus();
		}

		frame->UpdateLODInfo();

		m_bPainting = false;
	}

	// Reset the number of mousemoves we've gotten since last redraw
	m_iConsecutiveMousemoves = 0;

	if (bFirstPaint)
		bFirstPaint = false;
}

void vtGLCanvas::OnClose(wxCloseEvent& event)
{
	m_bRunning = false;
}

void vtGLCanvas::OnSize(wxSizeEvent& event)
{
	static int count = 0;
	if (count < 3)
	{
		VTLOG("Canvas  OnSize: %d %d\n", event.GetSize().x, event.GetSize().y);
		count++;
	}
	SetCurrent();
	int width, height;
	GetClientSize(& width, & height);

	vtGetScene()->SetWindowSize(width, height);

	wxGLCanvas::OnSize(event);
}

void vtGLCanvas::OnChar(wxKeyEvent& event)
{
	long key = event.GetKeyCode();

	// pass the char to the frame for it to do "accelerator" shortcuts
	EnviroFrame *frame = (EnviroFrame*) GetParent();
	frame->OnChar(event);

	int flags = 0;

	if (event.ControlDown())
		flags |= VT_CONTROL;

	if (event.ShiftDown())
		flags |= VT_SHIFT;

	if (event.AltDown())
		flags |= VT_ALT;

	// pass the char to the vtlib Scene
	vtGetScene()->OnKey(key, flags);

	// Allow wxWindows to pass the event along to other code
	event.Skip();
}

void vtGLCanvas::OnKeyDown(wxKeyEvent& event)
{
	m_pbKeyState[event.m_keyCode] = true;
	event.Skip();
}

void vtGLCanvas::OnKeyUp(wxKeyEvent& event)
{
	m_pbKeyState[event.m_keyCode] = false;
	event.Skip();
}

void vtGLCanvas::OnMouseEvent(wxMouseEvent& event1)
{
	static bool bCapture = false;

	// turn WX mouse event into a VT mouse event
	vtMouseEvent event;
	wxEventType  ev = event1.GetEventType();
	if (ev == wxEVT_LEFT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_LEFT_UP) {
		event.type = VT_UP;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_MIDDLE_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_MIDDLE_UP) {
		event.type = VT_UP;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_RIGHT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_RIGHT_UP) {
		event.type = VT_UP;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_MOTION) {
		event.type = VT_MOVE;
		event.button = VT_NONE;
		m_iConsecutiveMousemoves++;		// Increment
	} else if (ev == wxEVT_MOUSEWHEEL) {
		event.type = VT_WHEEL;
		event.button = event1.GetWheelRotation() / event1.GetWheelDelta();
	} else {
		// ignored mouse events, such as wxEVT_LEAVE_WINDOW
		return;
	}

	if (ev == wxEVT_LEFT_DOWN || ev == wxEVT_MIDDLE_DOWN || ev == wxEVT_RIGHT_DOWN)
	{
//		VTLOG("DOWN: capture %d", bCapture);
		if (!bCapture)
		{
			CaptureMouse();
			bCapture = true;
//			VTLOG(" -> true");
		}
//		VTLOG("\n");
	}
	if (ev == wxEVT_LEFT_UP || ev == wxEVT_MIDDLE_UP || ev == wxEVT_RIGHT_UP)
	{
//		VTLOG("  UP: capture %d", bCapture);
		if (bCapture)
		{
			ReleaseMouse();
			bCapture = false;
//			VTLOG(" -> false");
		}
//		VTLOG("\n");
	}

	// Because of the way the event pump works, if it takes too long to
	//  handle a MouseMove event, then we might get the next MouseMove
	//  event without ever seeing a Redraw or Idle.  That's because the
	//  MouseMove events are considered higher priority in the queue.
	// So, to keep Enviro response smooth, we effectively ignore all but
	//  one MouseMove event per Draw event.
	if (ev == wxEVT_MOTION && m_iConsecutiveMousemoves > 1)
		return;

	event.flags = 0;
	wxCoord xpos, ypos;
	event1.GetPosition(&xpos, &ypos);
	event.pos.Set(xpos, ypos);

	if (event1.ControlDown())
		event.flags |= VT_CONTROL;

	if (event1.ShiftDown())
		event.flags |= VT_SHIFT;

	if (event1.AltDown())
		event.flags |= VT_ALT;

	// inform vtlib scene, which informs the engines
	vtGetScene()->OnMouse(event);

	// inform Enviro app
	g_App.OnMouse(event);
}

void vtGLCanvas::OnEraseBackground(wxEraseEvent& event)
{
	// Do nothing, to avoid flashing.
}

void vtGLCanvas::OnIdle(wxIdleEvent &event)
{
	// We use the "Refresh on Idle" approach to continuous rendering.
	if (m_bRunning)
		Refresh(FALSE);
}

<|endoftext|>


<commit_before>#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/XmlOutputter.h>

#include <OgrePlatform.h>

#include "Suite.h"

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{

    setUpSuite();

    // Create the event manager and test controller
    CPPUNIT_NS::TestResult controller;

    // Add a listener that colllects test result
    CPPUNIT_NS::TestResultCollector result;
    controller.addListener( &result );

    // Add a listener that print dots as test run.
    CPPUNIT_NS::BriefTestProgressListener progress;
    controller.addListener( &progress );

    // Add the top suite to the test runner
    CPPUNIT_NS::TestRunner runner;
    runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
    runner.run( controller );

    // Print test results to a file
	std::ofstream ofile("OgreTestResults.xml");

    CPPUNIT_NS::XmlOutputter xmlOut(&result, ofile);
    xmlOut.write();

    tearDownSuite();

    return result.wasSuccessful() ? 0 : 1;

}
<commit_msg>Always return 0 from the tests. Success will be determined by the output.<commit_after>#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/XmlOutputter.h>

#include <OgrePlatform.h>

#include "Suite.h"

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{

    setUpSuite();

    // Create the event manager and test controller
    CPPUNIT_NS::TestResult controller;

    // Add a listener that colllects test result
    CPPUNIT_NS::TestResultCollector result;
    controller.addListener( &result );

    // Add a listener that print dots as test run.
    CPPUNIT_NS::BriefTestProgressListener progress;
    controller.addListener( &progress );

    // Add the top suite to the test runner
    CPPUNIT_NS::TestRunner runner;
    runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
    runner.run( controller );

    // Print test results to a file
	std::ofstream ofile("OgreTestResults.xml");

    CPPUNIT_NS::XmlOutputter xmlOut(&result, ofile);
    xmlOut.write();

    tearDownSuite();

    return 0;
}
<|endoftext|>


<commit_before>#include "ssdt.h"
#include "undocumented.h"
#include "pe.h"
#include "log.h"
#include "ntdll.h"

//structures
struct SSDTStruct
{
	LONG* pServiceTable;
	PVOID pCounterTable;
#ifdef _WIN64
	ULONGLONG NumberOfServices;
#else
	ULONG NumberOfServices;
#endif
	PCHAR pArgumentTable;
};

//Based on: https://code.google.com/p/volatility/issues/detail?id=189#c2
static SSDTStruct* SSDTfind()
{
	static SSDTStruct* SSDT = 0;
	if (!SSDT)
	{
		UNICODE_STRING routineName;
#ifndef _WIN64
		//x86 code
		RtlInitUnicodeString(&routineName, L"KeServiceDescriptorTable");
		SSDT = MmGetSystemRoutineAddress(&routineName);
#else
		//x64 code
		RtlInitUnicodeString(&routineName, L"KeAddSystemServiceTable");
		PVOID KeASST = MmGetSystemRoutineAddress(&routineName);
		if (!KeASST)
		{
			Log("[TITANHIDE] Failed to find KeAddSystemServiceTable!\n");
			return 0;
		}
		unsigned char function[1024];
		unsigned int function_size = 0;
		RtlCopyMemory(function, KeASST, sizeof(function));
		for (unsigned int i = 0; i < sizeof(function); i++)
		{
			if (function[i] == 0xC3) //ret
			{
				function_size = i + 1;
				break;
			}
		}
		if (!function_size)
		{
			Log("[TITANHIDE] Failed to get function size of KeAddSystemServiceTable!\n");
			return 0;
		}

		/*
		000000014050EA4A 48 C1 E0 05                shl rax, 5
		000000014050EA4E 48 83 BC 18 80 3A 36 00 00 cmp qword ptr [rax+rbx+363A80h], 0 <- we are looking for this instruction
		000000014050EA57 0F 85 B2 5C 0A 00          jnz loc_1405B470F
		000000014050EA5D 48 8D 8B C0 3A 36 00       lea rcx, rva KeServiceDescriptorTableShadow[rbx]
		000000014050EA64 48 03 C8                   add rcx, rax
		000000014050EA67 48 83 39 00                cmp qword ptr [rcx], 0
		*/
		int rvaSSDT = 0;
		for (unsigned int i = 0; i < function_size; i++)
		{
			if (((*(unsigned int*)(function + i)) & 0x00FFFFF0) == 0xBC8340 &&
				!*(unsigned char*)(function + i + 8)) //4?83bc?? ???????? 00 cmp qword ptr [r?+r?+????????h],0
			{
				rvaSSDT = *(unsigned int*)(function + i + 4);
				break;
			}
		}
		if (rvaSSDT) //this method worked
		{
			Log("[TITANHIDE] SSDT RVA: 0x%X\n", rvaSSDT);
			PVOID base = Undocumented::GetKernelBase();
			if (!base)
			{
				Log("[TITANHIDE] GetKernelBase() failed!\n");
				return 0;
			}
			Log("[TITANHIDE] GetKernelBase()->0x%p\n", base);
			SSDT = (SSDTStruct*)((unsigned char*)base + rvaSSDT);
		}

		/*
		Windows 10 Technical Preview:
		fffff800e21b30ec 757f             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		fffff800e21b30ee 48833deafee4ff00 cmp qword ptr [nt!KeServiceDescriptorTable+0x20 (fffff800e2002fe0)],0 <- we are looking for this instruction
		fffff800e21b30f6 7575             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		fffff800e21b30f8 48833da0fee4ff00 cmp qword ptr [nt!KeServiceDescriptorTableShadow+0x20 (fffff800e2002fa0)],0
		fffff800e21b3100 756b             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		*/
		int rvaFound = -1;
		for (unsigned int i = 0; i < function_size; i++)
		{
			if (((*(unsigned int*)(function + i)) & 0x00FFFFFF) == 0x3D8348 &&
				!*(unsigned char*)(function + i + 7)) //48833d ???????? 00 cmp qword ptr [X],0
			{
				rvaFound = i;
				rvaSSDT = *(unsigned int*)(function + i + 3);
				break;
			}
		}
		if (rvaFound == -1)
		{
			Log("[TITANHIDE] Failed to find pattern...\n");
			return 0;
		}
		//Sanity check SSDT & contents
		__try
		{
			SSDT = (SSDTStruct*)((ULONG_PTR)KeASST + rvaFound + rvaSSDT + 8 - 0x20);
			ULONG_PTR check = (ULONG_PTR)KeASST & 0xFFFFFFFF00000000;
			if (((ULONG_PTR)SSDT & 0xFFFFFFFF00000000 != check) ||
				((ULONG_PTR)SSDT->pServiceTable & 0xFFFFFFFF00000000) != check ||
				(SSDT->NumberOfServices & 0xFFFFFFFFFFFF0000) != 0 ||
				((ULONG_PTR)SSDT->pArgumentTable & 0xFFFFFFFF00000000) != check)
			{
				Log("[TITANHIDE] Found SSDT didn't pass all checks...\n");
				return 0;
			}
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			Log("[TITANHIDE] An exception was thrown while accessing the SSDT...\n");
			return 0;
		}
#endif
	}
	return SSDT;
}

PVOID SSDT::GetFunctionAddress(const char* apiname)
{
	//read address from SSDT
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return 0;
	}
	ULONG_PTR SSDTbase = (ULONG_PTR)SSDT->pServiceTable;
	if (!SSDTbase)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return 0;
	}
	ULONG readOffset = NTDLL::GetExportSsdtIndex(apiname);
	if (readOffset == -1)
		return 0;
	if (readOffset >= SSDT->NumberOfServices)
	{
		Log("[TITANHIDE] Invalid read offset...\n");
		return 0;
}
#ifdef _WIN64
	return (PVOID)((SSDT->pServiceTable[readOffset] >> 4) + SSDTbase);
#else
	return (PVOID)SSDT->pServiceTable[readOffset];
#endif
}

static void InterlockedSet(LONG* Destination, LONG Source)
{
	//Change memory properties.
	PMDL g_pmdl = IoAllocateMdl(Destination, sizeof(LONG), 0, 0, NULL);
	if (!g_pmdl)
		return;
	MmBuildMdlForNonPagedPool(g_pmdl);
	LONG* Mapped = (LONG*)MmMapLockedPages(g_pmdl, KernelMode);
	if (!Mapped)
	{
		IoFreeMdl(g_pmdl);
		return;
	}
	InterlockedExchange(Mapped, Source);
	//Restore memory properties.
	MmUnmapLockedPages((PVOID)Mapped, g_pmdl);
	IoFreeMdl(g_pmdl);
}

#ifdef _WIN64
static PVOID FindCaveAddress(PVOID CodeStart, ULONG CodeSize, ULONG CaveSize)
{
	unsigned char* Code = (unsigned char*)CodeStart;

	for (unsigned int i = 0, j = 0; i < CodeSize; i++)
	{
		if (Code[i] == 0x90 || Code[i] == 0xCC) //NOP or INT3
			j++;
		else
			j = 0;
		if (j == CaveSize)
			return (PVOID)((ULONG_PTR)CodeStart + i - CaveSize + 1);
	}
	return 0;
}
#endif //_WIN64

HOOK SSDT::Hook(const char* apiname, void* newfunc)
{
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return 0;
	}
	ULONG_PTR SSDTbase = (ULONG_PTR)SSDT->pServiceTable;
	if (!SSDTbase)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return 0;
	}
	ULONG FunctionIndex = NTDLL::GetExportSsdtIndex(apiname);
	if (FunctionIndex == -1)
		return 0;
	if (FunctionIndex >= SSDT->NumberOfServices)
	{
		Log("[TITANHIDE] Invalid API offset...\n");
		return 0;
	}

	HOOK hHook = 0;
	ULONG oldValue = SSDT->pServiceTable[FunctionIndex];
	ULONG newValue;

#ifdef _WIN64
	/*
	x64 SSDT Hook;
	1) find API addr
	2) get code page+size
	3) find cave address
	4) hook cave address (using hooklib)
	5) change SSDT value
	*/

	static ULONG CodeSize = 0;
	static PVOID CodeStart = 0;
	if (!CodeStart)
	{
		ULONG_PTR Lowest = SSDTbase;
		ULONG_PTR Highest = Lowest + 0x0FFFFFFF;
		Log("[TITANHIDE] Range: 0x%p-0x%p\n", Lowest, Highest);
		CodeSize = 0;
		CodeStart = PE::GetPageBase(Undocumented::GetKernelBase(), &CodeSize, (PVOID)((oldValue >> 4) + SSDTbase));
		if (!CodeStart || !CodeSize)
		{
			Log("[TITANHIDE] PeGetPageBase failed...\n");
			return 0;
		}
		Log("[TITANHIDE] CodeStart: 0x%p, CodeSize: 0x%X\n", CodeStart, CodeSize);
		if ((ULONG_PTR)CodeStart < Lowest) //start of the page is out of range (impossible, but whatever)
		{
			CodeSize -= (ULONG)(Lowest - (ULONG_PTR)CodeStart);
			CodeStart = (PVOID)Lowest;
			Log("[TITANHIDE] CodeStart: 0x%p, CodeSize: 0x%X\n", CodeStart, CodeSize);
		}
		Log("[TITANHIDE] Range: 0x%p-0x%p\n", CodeStart, (ULONG_PTR)CodeStart + CodeSize);
	}

	PVOID CaveAddress = FindCaveAddress(CodeStart, CodeSize, sizeof(HOOKOPCODES));
	if (!CaveAddress)
	{
		Log("[TITANHIDE] FindCaveAddress failed...\n");
		return 0;
	}
	Log("[TITANHIDE] CaveAddress: 0x%p\n", CaveAddress);

	hHook = Hooklib::Hook(CaveAddress, (void*)newfunc);
	if (!hHook)
		return 0;

	newValue = (ULONG)((ULONG_PTR)CaveAddress - SSDTbase);
	newValue = (newValue << 4) | oldValue & 0xF;

	//update HOOK structure
	hHook->SSDTindex = FunctionIndex;
	hHook->SSDTold = oldValue;
	hHook->SSDTnew = newValue;
	hHook->SSDTaddress = (oldValue >> 4) + SSDTbase;

#else
	/*
	x86 SSDT Hook:
	1) change SSDT value
	*/
	newValue = (ULONG)newfunc;

	hHook = (HOOK)RtlAllocateMemory(true, sizeof(HOOKSTRUCT));

	//update HOOK structure
	hHook->SSDTindex = FunctionIndex;
	hHook->SSDTold = oldValue;
	hHook->SSDTnew = newValue;
	hHook->SSDTaddress = oldValue;

#endif

	InterlockedSet(&SSDT->pServiceTable[FunctionIndex], newValue);

	Log("[TITANHIDE] SSDThook(%s:0x%p, 0x%p)\n", apiname, hHook->SSDTold, hHook->SSDTnew);

	return hHook;
}

void SSDT::Hook(HOOK hHook)
{
	if (!hHook)
		return;
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return;
	}
	LONG* SSDT_Table = SSDT->pServiceTable;
	if (!SSDT_Table)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return;
	}
	InterlockedSet(&SSDT_Table[hHook->SSDTindex], hHook->SSDTnew);
}

void SSDT::Unhook(HOOK hHook, bool free)
{
	if (!hHook)
		return;
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return;
	}
	LONG* SSDT_Table = SSDT->pServiceTable;
	if (!SSDT_Table)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return;
	}
	InterlockedSet(&SSDT_Table[hHook->SSDTindex], hHook->SSDTold);
#ifdef _WIN64
	if (free)
		Hooklib::Unhook(hHook, true);
#else
	UNREFERENCED_PARAMETER(free);
#endif
	}<commit_msg>fixed type<commit_after>#include "ssdt.h"
#include "undocumented.h"
#include "pe.h"
#include "log.h"
#include "ntdll.h"

//structures
struct SSDTStruct
{
	LONG* pServiceTable;
	PVOID pCounterTable;
#ifdef _WIN64
	ULONGLONG NumberOfServices;
#else
	ULONG NumberOfServices;
#endif
	PCHAR pArgumentTable;
};

//Based on: https://code.google.com/p/volatility/issues/detail?id=189#c2
static SSDTStruct* SSDTfind()
{
	static SSDTStruct* SSDT = 0;
	if (!SSDT)
	{
		UNICODE_STRING routineName;
#ifndef _WIN64
		//x86 code
		RtlInitUnicodeString(&routineName, L"KeServiceDescriptorTable");
		SSDT = MmGetSystemRoutineAddress(&routineName);
#else
		//x64 code
		RtlInitUnicodeString(&routineName, L"KeAddSystemServiceTable");
		PVOID KeASST = MmGetSystemRoutineAddress(&routineName);
		if (!KeASST)
		{
			Log("[TITANHIDE] Failed to find KeAddSystemServiceTable!\n");
			return 0;
		}
		unsigned char function[1024];
		unsigned int function_size = 0;
		RtlCopyMemory(function, KeASST, sizeof(function));
		for (unsigned int i = 0; i < sizeof(function); i++)
		{
			if (function[i] == 0xC3) //ret
			{
				function_size = i + 1;
				break;
			}
		}
		if (!function_size)
		{
			Log("[TITANHIDE] Failed to get function size of KeAddSystemServiceTable!\n");
			return 0;
		}

		/*
		000000014050EA4A 48 C1 E0 05                shl rax, 5
		000000014050EA4E 48 83 BC 18 80 3A 36 00 00 cmp qword ptr [rax+rbx+363A80h], 0 <- we are looking for this instruction
		000000014050EA57 0F 85 B2 5C 0A 00          jnz loc_1405B470F
		000000014050EA5D 48 8D 8B C0 3A 36 00       lea rcx, rva KeServiceDescriptorTableShadow[rbx]
		000000014050EA64 48 03 C8                   add rcx, rax
		000000014050EA67 48 83 39 00                cmp qword ptr [rcx], 0
		*/
		int rvaSSDT = 0;
		for (unsigned int i = 0; i < function_size; i++)
		{
			if (((*(unsigned int*)(function + i)) & 0x00FFFFF0) == 0xBC8340 &&
				!*(unsigned char*)(function + i + 8)) //4?83bc?? ???????? 00 cmp qword ptr [r?+r?+????????h],0
			{
				rvaSSDT = *(int*)(function + i + 4);
				break;
			}
		}
		if (rvaSSDT) //this method worked
		{
			Log("[TITANHIDE] SSDT RVA: 0x%X\n", rvaSSDT);
			PVOID base = Undocumented::GetKernelBase();
			if (!base)
			{
				Log("[TITANHIDE] GetKernelBase() failed!\n");
				return 0;
			}
			Log("[TITANHIDE] GetKernelBase()->0x%p\n", base);
			SSDT = (SSDTStruct*)((unsigned char*)base + rvaSSDT);
		}

		/*
		Windows 10 Technical Preview:
		fffff800e21b30ec 757f             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		fffff800e21b30ee 48833deafee4ff00 cmp qword ptr [nt!KeServiceDescriptorTable+0x20 (fffff800e2002fe0)],0 <- we are looking for this instruction
		fffff800e21b30f6 7575             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		fffff800e21b30f8 48833da0fee4ff00 cmp qword ptr [nt!KeServiceDescriptorTableShadow+0x20 (fffff800e2002fa0)],0
		fffff800e21b3100 756b             jne nt!KeAddSystemServiceTable+0x91 (fffff800e21b316d)
		*/
		int rvaFound = -1;
		for (unsigned int i = 0; i < function_size; i++)
		{
			if (((*(unsigned int*)(function + i)) & 0x00FFFFFF) == 0x3D8348 &&
				!*(unsigned char*)(function + i + 7)) //48833d ???????? 00 cmp qword ptr [X],0
			{
				rvaFound = i;
				rvaSSDT = *(int*)(function + i + 3);
				break;
			}
		}
		if (rvaFound == -1)
		{
			Log("[TITANHIDE] Failed to find pattern...\n");
			return 0;
		}
		//Sanity check SSDT & contents
		__try
		{
			SSDT = (SSDTStruct*)((ULONG_PTR)KeASST + rvaFound + rvaSSDT + 8 - 0x20);
			ULONG_PTR check = (ULONG_PTR)KeASST & 0xFFFFFFFF00000000;
			if (((ULONG_PTR)SSDT & 0xFFFFFFFF00000000 != check) ||
				((ULONG_PTR)SSDT->pServiceTable & 0xFFFFFFFF00000000) != check ||
				(SSDT->NumberOfServices & 0xFFFFFFFFFFFF0000) != 0 ||
				((ULONG_PTR)SSDT->pArgumentTable & 0xFFFFFFFF00000000) != check)
			{
				Log("[TITANHIDE] Found SSDT didn't pass all checks...\n");
				return 0;
			}
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			Log("[TITANHIDE] An exception was thrown while accessing the SSDT...\n");
			return 0;
		}
#endif
	}
	return SSDT;
}

PVOID SSDT::GetFunctionAddress(const char* apiname)
{
	//read address from SSDT
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return 0;
	}
	ULONG_PTR SSDTbase = (ULONG_PTR)SSDT->pServiceTable;
	if (!SSDTbase)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return 0;
	}
	ULONG readOffset = NTDLL::GetExportSsdtIndex(apiname);
	if (readOffset == -1)
		return 0;
	if (readOffset >= SSDT->NumberOfServices)
	{
		Log("[TITANHIDE] Invalid read offset...\n");
		return 0;
}
#ifdef _WIN64
	return (PVOID)((SSDT->pServiceTable[readOffset] >> 4) + SSDTbase);
#else
	return (PVOID)SSDT->pServiceTable[readOffset];
#endif
}

static void InterlockedSet(LONG* Destination, LONG Source)
{
	//Change memory properties.
	PMDL g_pmdl = IoAllocateMdl(Destination, sizeof(LONG), 0, 0, NULL);
	if (!g_pmdl)
		return;
	MmBuildMdlForNonPagedPool(g_pmdl);
	LONG* Mapped = (LONG*)MmMapLockedPages(g_pmdl, KernelMode);
	if (!Mapped)
	{
		IoFreeMdl(g_pmdl);
		return;
	}
	InterlockedExchange(Mapped, Source);
	//Restore memory properties.
	MmUnmapLockedPages((PVOID)Mapped, g_pmdl);
	IoFreeMdl(g_pmdl);
}

#ifdef _WIN64
static PVOID FindCaveAddress(PVOID CodeStart, ULONG CodeSize, ULONG CaveSize)
{
	unsigned char* Code = (unsigned char*)CodeStart;

	for (unsigned int i = 0, j = 0; i < CodeSize; i++)
	{
		if (Code[i] == 0x90 || Code[i] == 0xCC) //NOP or INT3
			j++;
		else
			j = 0;
		if (j == CaveSize)
			return (PVOID)((ULONG_PTR)CodeStart + i - CaveSize + 1);
	}
	return 0;
}
#endif //_WIN64

HOOK SSDT::Hook(const char* apiname, void* newfunc)
{
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return 0;
	}
	ULONG_PTR SSDTbase = (ULONG_PTR)SSDT->pServiceTable;
	if (!SSDTbase)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return 0;
	}
	ULONG FunctionIndex = NTDLL::GetExportSsdtIndex(apiname);
	if (FunctionIndex == -1)
		return 0;
	if (FunctionIndex >= SSDT->NumberOfServices)
	{
		Log("[TITANHIDE] Invalid API offset...\n");
		return 0;
	}

	HOOK hHook = 0;
	ULONG oldValue = SSDT->pServiceTable[FunctionIndex];
	ULONG newValue;

#ifdef _WIN64
	/*
	x64 SSDT Hook;
	1) find API addr
	2) get code page+size
	3) find cave address
	4) hook cave address (using hooklib)
	5) change SSDT value
	*/

	static ULONG CodeSize = 0;
	static PVOID CodeStart = 0;
	if (!CodeStart)
	{
		ULONG_PTR Lowest = SSDTbase;
		ULONG_PTR Highest = Lowest + 0x0FFFFFFF;
		Log("[TITANHIDE] Range: 0x%p-0x%p\n", Lowest, Highest);
		CodeSize = 0;
		CodeStart = PE::GetPageBase(Undocumented::GetKernelBase(), &CodeSize, (PVOID)((oldValue >> 4) + SSDTbase));
		if (!CodeStart || !CodeSize)
		{
			Log("[TITANHIDE] PeGetPageBase failed...\n");
			return 0;
		}
		Log("[TITANHIDE] CodeStart: 0x%p, CodeSize: 0x%X\n", CodeStart, CodeSize);
		if ((ULONG_PTR)CodeStart < Lowest) //start of the page is out of range (impossible, but whatever)
		{
			CodeSize -= (ULONG)(Lowest - (ULONG_PTR)CodeStart);
			CodeStart = (PVOID)Lowest;
			Log("[TITANHIDE] CodeStart: 0x%p, CodeSize: 0x%X\n", CodeStart, CodeSize);
		}
		Log("[TITANHIDE] Range: 0x%p-0x%p\n", CodeStart, (ULONG_PTR)CodeStart + CodeSize);
	}

	PVOID CaveAddress = FindCaveAddress(CodeStart, CodeSize, sizeof(HOOKOPCODES));
	if (!CaveAddress)
	{
		Log("[TITANHIDE] FindCaveAddress failed...\n");
		return 0;
	}
	Log("[TITANHIDE] CaveAddress: 0x%p\n", CaveAddress);

	hHook = Hooklib::Hook(CaveAddress, (void*)newfunc);
	if (!hHook)
		return 0;

	newValue = (ULONG)((ULONG_PTR)CaveAddress - SSDTbase);
	newValue = (newValue << 4) | oldValue & 0xF;

	//update HOOK structure
	hHook->SSDTindex = FunctionIndex;
	hHook->SSDTold = oldValue;
	hHook->SSDTnew = newValue;
	hHook->SSDTaddress = (oldValue >> 4) + SSDTbase;

#else
	/*
	x86 SSDT Hook:
	1) change SSDT value
	*/
	newValue = (ULONG)newfunc;

	hHook = (HOOK)RtlAllocateMemory(true, sizeof(HOOKSTRUCT));

	//update HOOK structure
	hHook->SSDTindex = FunctionIndex;
	hHook->SSDTold = oldValue;
	hHook->SSDTnew = newValue;
	hHook->SSDTaddress = oldValue;

#endif

	InterlockedSet(&SSDT->pServiceTable[FunctionIndex], newValue);

	Log("[TITANHIDE] SSDThook(%s:0x%p, 0x%p)\n", apiname, hHook->SSDTold, hHook->SSDTnew);

	return hHook;
}

void SSDT::Hook(HOOK hHook)
{
	if (!hHook)
		return;
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return;
	}
	LONG* SSDT_Table = SSDT->pServiceTable;
	if (!SSDT_Table)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return;
	}
	InterlockedSet(&SSDT_Table[hHook->SSDTindex], hHook->SSDTnew);
}

void SSDT::Unhook(HOOK hHook, bool free)
{
	if (!hHook)
		return;
	SSDTStruct* SSDT = SSDTfind();
	if (!SSDT)
	{
		Log("[TITANHIDE] SSDT not found...\n");
		return;
	}
	LONG* SSDT_Table = SSDT->pServiceTable;
	if (!SSDT_Table)
	{
		Log("[TITANHIDE] ServiceTable not found...\n");
		return;
	}
	InterlockedSet(&SSDT_Table[hHook->SSDTindex], hHook->SSDTold);
#ifdef _WIN64
	if (free)
		Hooklib::Unhook(hHook, true);
#else
	UNREFERENCED_PARAMETER(free);
#endif
	}<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/task_manager_handler.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/webpreferences.h"

namespace {

Value* CreateColumnValue(const TaskManagerModel* tm,
                         const std::string& column_name,
                         const int i) {
  if (column_name == "uniqueId")
    return Value::CreateIntegerValue(tm->GetResourceUniqueId(i));
  if (column_name == "type")
    return Value::CreateStringValue(
        TaskManager::Resource::GetResourceTypeAsString(
        tm->GetResourceType(i)));
  if (column_name == "processId")
    return Value::CreateStringValue(tm->GetResourceProcessId(i));
  if (column_name == "processIdValue")
    return Value::CreateIntegerValue(tm->GetProcessId(i));
  if (column_name == "cpuUsage")
    return Value::CreateStringValue(tm->GetResourceCPUUsage(i));
  if (column_name == "cpuUsageValue")
    return Value::CreateDoubleValue(tm->GetCPUUsage(i));
  if (column_name == "privateMemory")
    return Value::CreateStringValue(tm->GetResourcePrivateMemory(i));
  if (column_name == "privateMemoryValue") {
    size_t private_memory;
    tm->GetPrivateMemory(i, &private_memory);
    return Value::CreateDoubleValue(private_memory);
  }
  if (column_name == "sharedMemory")
    return Value::CreateStringValue(tm->GetResourceSharedMemory(i));
  if (column_name == "sharedMemoryValue") {
    size_t shared_memory;
    tm->GetSharedMemory(i, &shared_memory);
    return Value::CreateDoubleValue(shared_memory);
  }
  if (column_name == "physicalMemory")
    return Value::CreateStringValue(tm->GetResourcePhysicalMemory(i));
  if (column_name == "physicalMemoryValue") {
    size_t physical_memory;
    tm->GetPhysicalMemory(i, &physical_memory);
    return Value::CreateDoubleValue(physical_memory);
  }
  if (column_name == "icon")
    return Value::CreateStringValue(
               web_ui_util::GetImageDataUrl(tm->GetResourceIcon(i)));
  if (column_name == "title")
    return Value::CreateStringValue(tm->GetResourceTitle(i));
  if (column_name == "profileName")
    return Value::CreateStringValue(tm->GetResourceProfileName(i));
  if (column_name == "networkUsage")
    return Value::CreateStringValue(tm->GetResourceNetworkUsage(i));
  if (column_name == "networkUsageValue")
    return Value::CreateDoubleValue(tm->GetNetworkUsage(i));
  if (column_name == "webCoreImageCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreImageCacheSize(i));
  if (column_name == "webCoreImageCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.images.size);
  }
  if (column_name == "webCoreScriptsCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreScriptsCacheSize(i));
  if (column_name == "webCoreScriptsCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.scripts.size);
  }
  if (column_name == "webCoreCSSCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreCSSCacheSize(i));
  if (column_name == "webCoreCSSCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
  }
  if (column_name == "fps")
    return Value::CreateStringValue(tm->GetResourceFPS(i));
  if (column_name == "fpsValue") {
    float fps;
    tm->GetFPS(i, &fps);
    return Value::CreateDoubleValue(fps);
  }
  if (column_name == "sqliteMemoryUsed")
    return Value::CreateStringValue(tm->GetResourceSqliteMemoryUsed(i));
  if (column_name == "sqliteMemoryUsedValue") {
    size_t sqlite_memory;
    tm->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
    return Value::CreateDoubleValue(sqlite_memory);
  }
  if (column_name == "goatsTeleported")
    return Value::CreateStringValue(tm->GetResourceGoatsTeleported(i));
  if (column_name == "goatsTeleportedValue")
    return Value::CreateIntegerValue(tm->GetGoatsTeleported(i));
  if (column_name == "v8MemoryAllocatedSize")
    return Value::CreateStringValue(tm->GetResourceV8MemoryAllocatedSize(i));
  if (column_name == "v8MemoryAllocatedSizeValue") {
    size_t v8_memory;
    tm->GetV8Memory(i, &v8_memory);
    return Value::CreateDoubleValue(v8_memory);
  }
  if (column_name == "canInspect")
    return Value::CreateBooleanValue(tm->CanInspect(i));
  if (column_name == "canActivate")
    return Value::CreateBooleanValue(tm->CanActivate(i));

  NOTREACHED();
  return NULL;
}

void CreateGroupColumnList(const TaskManagerModel* tm,
                           const std::string& column_name,
                           const int index,
                           const int length,
                           DictionaryValue* val) {
  ListValue* list = new ListValue();
  for (int i = index; i < (index + length); ++i) {
    list->Append(CreateColumnValue(tm, column_name, i));
  }
  val->Set(column_name, list);
}

struct ColumnType {
  const char* column_id;
  // Whether the column has the real value separately or not, instead of the
  // formatted value to display.
  const bool has_real_value;
  // Whether the column has single datum or multiple data in each group.
  const bool has_multiple_data;
};

const ColumnType kColumnsList[] = {
  {"type", false, false},
  {"processId", true, false},
  {"cpuUsage", true, false},
  {"physicalMemory", true, false},
  {"sharedMemory", true, false},
  {"privateMemory", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreScriptsCacheSize", true, false},
  {"webCoreCSSCacheSize", true, false},
  {"sqliteMemoryUsed", true, false},
  {"v8MemoryAllocatedSize", true, false},
  {"icon", false, true},
  {"title", false, true},
  {"profileName", false, true},
  {"networkUsage", true, true},
  {"fps", true, true},
  {"goatsTeleported", true, true},
  {"canInspect", false, true},
  {"canActivate", false, true}
};

DictionaryValue* CreateTaskGroupValue(
    const TaskManagerModel* tm,
    const int group_index,
    const std::set<std::string>& columns) {
  DictionaryValue* val = new DictionaryValue();

  const int group_count = tm->GroupCount();
  if (group_index >= group_count)
     return val;

  int index = tm->GetResourceIndexForGroup(group_index, 0);
  int length = tm->GetGroupRangeForResource(index).second;

  // Forces to set following 3 columns regardless of |enable_columns|.
  val->SetInteger("index", index);
  val->SetBoolean("isBackgroundResource",
                  tm->IsBackgroundResource(index));
  CreateGroupColumnList(tm, "uniqueId", index, length, val);
  CreateGroupColumnList(tm, "processId", index, 1, val);

  for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
    const std::string column_id = kColumnsList[i].column_id;

    if (columns.find(column_id) == columns.end())
      continue;

    int column_length = kColumnsList[i].has_multiple_data ? length : 1;
    CreateGroupColumnList(tm, column_id, index, column_length, val);

    if (kColumnsList[i].has_real_value)
      CreateGroupColumnList(tm, column_id + "Value", index, column_length, val);
  }

  return val;
}

}  // namespace

TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
    : task_manager_(tm),
      model_(tm->model()),
      is_enabled_(false) {
}

TaskManagerHandler::~TaskManagerHandler() {
  DisableTaskManager(NULL);
}

// TaskManagerHandler, public: -----------------------------------------------

void TaskManagerHandler::OnModelChanged() {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
}

void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
}

void TaskManagerHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("killProcesses",
      base::Bind(&TaskManagerHandler::HandleKillProcesses,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("inspect",
      base::Bind(&TaskManagerHandler::HandleInspect,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("activatePage",
      base::Bind(&TaskManagerHandler::HandleActivatePage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openAboutMemory",
      base::Bind(&TaskManagerHandler::OpenAboutMemory,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableTaskManager",
      base::Bind(&TaskManagerHandler::EnableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("disableTaskManager",
      base::Bind(&TaskManagerHandler::DisableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setUpdateColumn",
      base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
                 base::Unretained(this)));
}

static int parseIndex(const Value* value) {
  int index = -1;
  string16 string16_index;
  double double_index;
  if (value->GetAsString(&string16_index)) {
    bool converted = base::StringToInt(string16_index, &index);
    DCHECK(converted);
  } else if (value->GetAsDouble(&double_index)) {
    index = static_cast<int>(double_index);
  } else {
    value->GetAsInteger(&index);
  }
  return index;
}

void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->KillProcess(resource_index);
  }
}

void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->ActivateProcess(resource_index);
    break;
  }
}

void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    if (model_->CanInspect(resource_index))
      model_->Inspect(resource_index);
    break;
  }
}

void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
  if (!is_enabled_)
    return;

  is_enabled_ = false;
  model_->StopUpdating();
  model_->RemoveObserver(this);
}

void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
  if (is_enabled_)
    return;

  is_enabled_ = true;

  OnGroupChanged(0, model_->GroupCount());

  model_->AddObserver(this);
  model_->StartUpdating();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
      content::Source<TaskManagerModel>(model_),
      content::NotificationService::NoDetails());
}

void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
  if (rvh && rvh->delegate()) {
    WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
    webkit_prefs.allow_scripts_to_close_windows = true;
    rvh->UpdateWebkitPreferences(webkit_prefs);
  } else {
    DCHECK(false);
  }

  task_manager_->OpenAboutMemory();
}

void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
  DCHECK_EQ(2U, args->GetSize());

  bool ret = true;
  std::string column_id;
  ret &= args->GetString(0, &column_id);
  bool is_enabled;
  ret &= args->GetBoolean(1, &is_enabled);
  DCHECK(ret);

  if (is_enabled)
    enabled_columns_.insert(column_id);
  else
    enabled_columns_.erase(column_id);
}

// TaskManagerHandler, private: -----------------------------------------------

bool TaskManagerHandler::is_alive() {
  return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
}

void TaskManagerHandler::OnGroupChanged(const int group_start,
                                        const int group_length) {
  base::FundamentalValue start_value(group_start);
  base::FundamentalValue length_value(group_length);
  base::ListValue tasks_value;

  for (int i = 0; i < group_length; ++i)
    tasks_value.Append(
        CreateTaskGroupValue(model_, group_start + i, enabled_columns_));

  if (is_enabled_ && is_alive()) {
    web_ui()->CallJavascriptFunction("taskChanged",
                                     start_value, length_value, tasks_value);
  }
}

void TaskManagerHandler::OnGroupAdded(const int group_start,
                                      const int group_length) {
}

void TaskManagerHandler::OnGroupRemoved(const int group_start,
                                        const int group_length) {
}

void TaskManagerHandler::OnReadyPeriodicalUpdate() {
}
<commit_msg>WebUI TaskManager: Make the button "End process" grayed on selecting the browser process.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/task_manager_handler.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/webpreferences.h"

namespace {

Value* CreateColumnValue(const TaskManagerModel* tm,
                         const std::string& column_name,
                         const int i) {
  if (column_name == "uniqueId")
    return Value::CreateIntegerValue(tm->GetResourceUniqueId(i));
  if (column_name == "type")
    return Value::CreateStringValue(
        TaskManager::Resource::GetResourceTypeAsString(
        tm->GetResourceType(i)));
  if (column_name == "processId")
    return Value::CreateStringValue(tm->GetResourceProcessId(i));
  if (column_name == "processIdValue")
    return Value::CreateIntegerValue(tm->GetProcessId(i));
  if (column_name == "cpuUsage")
    return Value::CreateStringValue(tm->GetResourceCPUUsage(i));
  if (column_name == "cpuUsageValue")
    return Value::CreateDoubleValue(tm->GetCPUUsage(i));
  if (column_name == "privateMemory")
    return Value::CreateStringValue(tm->GetResourcePrivateMemory(i));
  if (column_name == "privateMemoryValue") {
    size_t private_memory;
    tm->GetPrivateMemory(i, &private_memory);
    return Value::CreateDoubleValue(private_memory);
  }
  if (column_name == "sharedMemory")
    return Value::CreateStringValue(tm->GetResourceSharedMemory(i));
  if (column_name == "sharedMemoryValue") {
    size_t shared_memory;
    tm->GetSharedMemory(i, &shared_memory);
    return Value::CreateDoubleValue(shared_memory);
  }
  if (column_name == "physicalMemory")
    return Value::CreateStringValue(tm->GetResourcePhysicalMemory(i));
  if (column_name == "physicalMemoryValue") {
    size_t physical_memory;
    tm->GetPhysicalMemory(i, &physical_memory);
    return Value::CreateDoubleValue(physical_memory);
  }
  if (column_name == "icon")
    return Value::CreateStringValue(
               web_ui_util::GetImageDataUrl(tm->GetResourceIcon(i)));
  if (column_name == "title")
    return Value::CreateStringValue(tm->GetResourceTitle(i));
  if (column_name == "profileName")
    return Value::CreateStringValue(tm->GetResourceProfileName(i));
  if (column_name == "networkUsage")
    return Value::CreateStringValue(tm->GetResourceNetworkUsage(i));
  if (column_name == "networkUsageValue")
    return Value::CreateDoubleValue(tm->GetNetworkUsage(i));
  if (column_name == "webCoreImageCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreImageCacheSize(i));
  if (column_name == "webCoreImageCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.images.size);
  }
  if (column_name == "webCoreScriptsCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreScriptsCacheSize(i));
  if (column_name == "webCoreScriptsCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.scripts.size);
  }
  if (column_name == "webCoreCSSCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreCSSCacheSize(i));
  if (column_name == "webCoreCSSCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
  }
  if (column_name == "fps")
    return Value::CreateStringValue(tm->GetResourceFPS(i));
  if (column_name == "fpsValue") {
    float fps;
    tm->GetFPS(i, &fps);
    return Value::CreateDoubleValue(fps);
  }
  if (column_name == "sqliteMemoryUsed")
    return Value::CreateStringValue(tm->GetResourceSqliteMemoryUsed(i));
  if (column_name == "sqliteMemoryUsedValue") {
    size_t sqlite_memory;
    tm->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
    return Value::CreateDoubleValue(sqlite_memory);
  }
  if (column_name == "goatsTeleported")
    return Value::CreateStringValue(tm->GetResourceGoatsTeleported(i));
  if (column_name == "goatsTeleportedValue")
    return Value::CreateIntegerValue(tm->GetGoatsTeleported(i));
  if (column_name == "v8MemoryAllocatedSize")
    return Value::CreateStringValue(tm->GetResourceV8MemoryAllocatedSize(i));
  if (column_name == "v8MemoryAllocatedSizeValue") {
    size_t v8_memory;
    tm->GetV8Memory(i, &v8_memory);
    return Value::CreateDoubleValue(v8_memory);
  }
  if (column_name == "canInspect")
    return Value::CreateBooleanValue(tm->CanInspect(i));
  if (column_name == "canActivate")
    return Value::CreateBooleanValue(tm->CanActivate(i));

  NOTREACHED();
  return NULL;
}

void CreateGroupColumnList(const TaskManagerModel* tm,
                           const std::string& column_name,
                           const int index,
                           const int length,
                           DictionaryValue* val) {
  ListValue* list = new ListValue();
  for (int i = index; i < (index + length); ++i) {
    list->Append(CreateColumnValue(tm, column_name, i));
  }
  val->Set(column_name, list);
}

struct ColumnType {
  const char* column_id;
  // Whether the column has the real value separately or not, instead of the
  // formatted value to display.
  const bool has_real_value;
  // Whether the column has single datum or multiple data in each group.
  const bool has_multiple_data;
};

const ColumnType kColumnsList[] = {
  {"type", false, false},
  {"processId", true, false},
  {"cpuUsage", true, false},
  {"physicalMemory", true, false},
  {"sharedMemory", true, false},
  {"privateMemory", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreScriptsCacheSize", true, false},
  {"webCoreCSSCacheSize", true, false},
  {"sqliteMemoryUsed", true, false},
  {"v8MemoryAllocatedSize", true, false},
  {"icon", false, true},
  {"title", false, true},
  {"profileName", false, true},
  {"networkUsage", true, true},
  {"fps", true, true},
  {"goatsTeleported", true, true},
  {"canInspect", false, true},
  {"canActivate", false, true}
};

DictionaryValue* CreateTaskGroupValue(
    const TaskManagerModel* tm,
    const int group_index,
    const std::set<std::string>& columns) {
  DictionaryValue* val = new DictionaryValue();

  const int group_count = tm->GroupCount();
  if (group_index >= group_count)
     return val;

  int index = tm->GetResourceIndexForGroup(group_index, 0);
  int length = tm->GetGroupRangeForResource(index).second;

  // Forces to set following 3 columns regardless of |enable_columns|.
  val->SetInteger("index", index);
  val->SetBoolean("isBackgroundResource",
                  tm->IsBackgroundResource(index));
  CreateGroupColumnList(tm, "processId", index, 1, val);
  CreateGroupColumnList(tm, "type", index, length, val);
  CreateGroupColumnList(tm, "uniqueId", index, length, val);

  for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
    const std::string column_id = kColumnsList[i].column_id;

    if (columns.find(column_id) == columns.end())
      continue;

    int column_length = kColumnsList[i].has_multiple_data ? length : 1;
    CreateGroupColumnList(tm, column_id, index, column_length, val);

    if (kColumnsList[i].has_real_value)
      CreateGroupColumnList(tm, column_id + "Value", index, column_length, val);
  }

  return val;
}

}  // namespace

TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
    : task_manager_(tm),
      model_(tm->model()),
      is_enabled_(false) {
}

TaskManagerHandler::~TaskManagerHandler() {
  DisableTaskManager(NULL);
}

// TaskManagerHandler, public: -----------------------------------------------

void TaskManagerHandler::OnModelChanged() {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
}

void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
}

void TaskManagerHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("killProcesses",
      base::Bind(&TaskManagerHandler::HandleKillProcesses,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("inspect",
      base::Bind(&TaskManagerHandler::HandleInspect,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("activatePage",
      base::Bind(&TaskManagerHandler::HandleActivatePage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openAboutMemory",
      base::Bind(&TaskManagerHandler::OpenAboutMemory,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableTaskManager",
      base::Bind(&TaskManagerHandler::EnableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("disableTaskManager",
      base::Bind(&TaskManagerHandler::DisableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setUpdateColumn",
      base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
                 base::Unretained(this)));
}

static int parseIndex(const Value* value) {
  int index = -1;
  string16 string16_index;
  double double_index;
  if (value->GetAsString(&string16_index)) {
    bool converted = base::StringToInt(string16_index, &index);
    DCHECK(converted);
  } else if (value->GetAsDouble(&double_index)) {
    index = static_cast<int>(double_index);
  } else {
    value->GetAsInteger(&index);
  }
  return index;
}

void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->KillProcess(resource_index);
  }
}

void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->ActivateProcess(resource_index);
    break;
  }
}

void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    if (model_->CanInspect(resource_index))
      model_->Inspect(resource_index);
    break;
  }
}

void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
  if (!is_enabled_)
    return;

  is_enabled_ = false;
  model_->StopUpdating();
  model_->RemoveObserver(this);
}

void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
  if (is_enabled_)
    return;

  is_enabled_ = true;

  OnGroupChanged(0, model_->GroupCount());

  model_->AddObserver(this);
  model_->StartUpdating();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
      content::Source<TaskManagerModel>(model_),
      content::NotificationService::NoDetails());
}

void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
  if (rvh && rvh->delegate()) {
    WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
    webkit_prefs.allow_scripts_to_close_windows = true;
    rvh->UpdateWebkitPreferences(webkit_prefs);
  } else {
    DCHECK(false);
  }

  task_manager_->OpenAboutMemory();
}

void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
  DCHECK_EQ(2U, args->GetSize());

  bool ret = true;
  std::string column_id;
  ret &= args->GetString(0, &column_id);
  bool is_enabled;
  ret &= args->GetBoolean(1, &is_enabled);
  DCHECK(ret);

  if (is_enabled)
    enabled_columns_.insert(column_id);
  else
    enabled_columns_.erase(column_id);
}

// TaskManagerHandler, private: -----------------------------------------------

bool TaskManagerHandler::is_alive() {
  return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
}

void TaskManagerHandler::OnGroupChanged(const int group_start,
                                        const int group_length) {
  base::FundamentalValue start_value(group_start);
  base::FundamentalValue length_value(group_length);
  base::ListValue tasks_value;

  for (int i = 0; i < group_length; ++i)
    tasks_value.Append(
        CreateTaskGroupValue(model_, group_start + i, enabled_columns_));

  if (is_enabled_ && is_alive()) {
    web_ui()->CallJavascriptFunction("taskChanged",
                                     start_value, length_value, tasks_value);
  }
}

void TaskManagerHandler::OnGroupAdded(const int group_start,
                                      const int group_length) {
}

void TaskManagerHandler::OnGroupRemoved(const int group_start,
                                        const int group_length) {
}

void TaskManagerHandler::OnReadyPeriodicalUpdate() {
}
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/network/network_device_handler_impl.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_ipconfig_client.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/shill_property_util.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

// TODO(armansito): Add bindings for these to service_constants.h
// (crbug.com/256889)
const char kShillErrorFailure[] = "org.chromium.flimflam.Error.Failure";
const char kShillErrorNotSupported[] =
    "org.chromium.flimflam.Error.NotSupported";

std::string GetErrorNameForShillError(const std::string& shill_error_name) {
  // TODO(armansito): Use the new SIM error names once the ones below get
  // deprecated (crbug.com/256855)
  if (shill_error_name == kShillErrorFailure)
    return NetworkDeviceHandler::kErrorFailure;
  if (shill_error_name == kShillErrorNotSupported)
    return NetworkDeviceHandler::kErrorNotSupported;
  if (shill_error_name == shill::kErrorIncorrectPinMsg)
    return NetworkDeviceHandler::kErrorIncorrectPin;
  if (shill_error_name == shill::kErrorPinBlockedMsg)
    return NetworkDeviceHandler::kErrorPinBlocked;
  if (shill_error_name == shill::kErrorPinRequiredMsg)
    return NetworkDeviceHandler::kErrorPinRequired;
  return NetworkDeviceHandler::kErrorUnknown;
}

void InvokeErrorCallback(const std::string& service_path,
                         const network_handler::ErrorCallback& error_callback,
                         const std::string& error_name) {
  std::string error_msg = "Device Error: " + error_name;
  NET_LOG_ERROR(error_msg, service_path);
  network_handler::RunErrorCallback(
      error_callback, service_path, error_name, error_msg);
}

void HandleShillCallFailure(
    const std::string& device_path,
    const network_handler::ErrorCallback& error_callback,
    const std::string& shill_error_name,
    const std::string& shill_error_message) {
  network_handler::ShillErrorCallbackFunction(
      GetErrorNameForShillError(shill_error_name),
      device_path,
      error_callback,
      shill_error_name,
      shill_error_message);
}

void IPConfigRefreshCallback(const std::string& ipconfig_path,
                             DBusMethodCallStatus call_status) {
  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
    NET_LOG_ERROR(
        base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status),
        ipconfig_path);
  } else {
    NET_LOG_EVENT("IPConfigs.Refresh Succeeded", ipconfig_path);
  }
}

void RefreshIPConfigsCallback(
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback,
    const std::string& device_path,
    const base::DictionaryValue& properties) {
  const base::ListValue* ip_configs;
  if (!properties.GetListWithoutPathExpansion(
          shill::kIPConfigsProperty, &ip_configs)) {
    NET_LOG_ERROR("RequestRefreshIPConfigs Failed", device_path);
    network_handler::ShillErrorCallbackFunction(
        "RequestRefreshIPConfigs Failed",
        device_path,
        error_callback,
        std::string("Missing ") + shill::kIPConfigsProperty, "");
    return;
  }

  for (size_t i = 0; i < ip_configs->GetSize(); i++) {
    std::string ipconfig_path;
    if (!ip_configs->GetString(i, &ipconfig_path))
      continue;
    DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
        dbus::ObjectPath(ipconfig_path),
        base::Bind(&IPConfigRefreshCallback, ipconfig_path));
  }
  // It is safe to invoke |callback| here instead of waiting for the
  // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will
  // be executed in order and thus before any further DBus requests that
  // |callback| may issue.
  if (!callback.is_null())
    callback.Run();
}

void ProposeScanCallback(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback,
    DBusMethodCallStatus call_status) {
  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
    network_handler::ShillErrorCallbackFunction(
        "Device.ProposeScan Failed",
        device_path,
        error_callback,
        base::StringPrintf("DBus call failed: %d", call_status), "");
    return;
  }
  NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path);
  if (!callback.is_null())
    callback.Run();
}

void SetDevicePropertyInternal(
    const std::string& device_path,
    const std::string& property_name,
    const base::Value& value,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
      dbus::ObjectPath(device_path),
      property_name,
      value,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

}  // namespace

NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
  network_state_handler_->RemoveObserver(this, FROM_HERE);
}

void NetworkDeviceHandlerImpl::GetDeviceProperties(
    const std::string& device_path,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback) const {
  DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
      dbus::ObjectPath(device_path),
      base::Bind(&network_handler::GetPropertiesCallback,
                 callback, error_callback, device_path));
}

void NetworkDeviceHandlerImpl::SetDeviceProperty(
    const std::string& device_path,
    const std::string& property_name,
    const base::Value& value,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  const char* const property_blacklist[] = {
      // Must only be changed by policy/owner through.
      shill::kCellularAllowRoamingProperty
  };

  for (size_t i = 0; i < arraysize(property_blacklist); ++i) {
    if (property_name == property_blacklist[i]) {
      InvokeErrorCallback(
          device_path,
          error_callback,
          "SetDeviceProperty called on blacklisted property " + property_name);
      return;
    }
  }

  SetDevicePropertyInternal(
      device_path, property_name, value, callback, error_callback);
}

void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  GetDeviceProperties(device_path,
                      base::Bind(&RefreshIPConfigsCallback,
                                 callback, error_callback),
                      error_callback);
}

void NetworkDeviceHandlerImpl::ProposeScan(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
      dbus::ObjectPath(device_path),
      base::Bind(&ProposeScanCallback, device_path, callback, error_callback));
}

void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
    const std::string& device_path,
    const std::string& network_id,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->Register(
      dbus::ObjectPath(device_path),
      network_id,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::SetCarrier(
    const std::string& device_path,
    const std::string& carrier,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
      dbus::ObjectPath(device_path),
      carrier,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::RequirePin(
    const std::string& device_path,
    bool require_pin,
    const std::string& pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
      dbus::ObjectPath(device_path),
      pin,
      require_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::EnterPin(
    const std::string& device_path,
    const std::string& pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
      dbus::ObjectPath(device_path),
      pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::UnblockPin(
    const std::string& device_path,
    const std::string& puk,
    const std::string& new_pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
      dbus::ObjectPath(device_path),
      puk,
      new_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::ChangePin(
    const std::string& device_path,
    const std::string& old_pin,
    const std::string& new_pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
      dbus::ObjectPath(device_path),
      old_pin,
      new_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
    const bool allow_roaming) {
  cellular_allow_roaming_ = allow_roaming;
  ApplyCellularAllowRoamingToShill();
}

void NetworkDeviceHandlerImpl::DeviceListChanged() {
  ApplyCellularAllowRoamingToShill();
}

NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
    : network_state_handler_(NULL),
      cellular_allow_roaming_(false) {}

void NetworkDeviceHandlerImpl::Init(
    NetworkStateHandler* network_state_handler) {
  DCHECK(network_state_handler);
  network_state_handler_ = network_state_handler;
  network_state_handler_->AddObserver(this, FROM_HERE);
}

void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
  NetworkStateHandler::DeviceStateList list;
  network_state_handler_->GetDeviceListByType(NetworkTypePattern::Cellular(),
                                              &list);
  if (list.empty()) {
    NET_LOG_DEBUG("No cellular device is available",
                  "Roaming is only supported by cellular devices.");
    return;
  }
  for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin();
      it != list.end(); ++it) {
    const DeviceState* device_state = *it;
    bool current_device_value;
    if (!device_state->properties().GetBooleanWithoutPathExpansion(
             shill::kCellularAllowRoamingProperty, &current_device_value)) {
      NET_LOG_ERROR(
          "Could not get \"allow roaming\" property from cellular "
          "device.",
          device_state->path());
      continue;
    }

    // If roaming is required by the provider, always try to set to true.
    bool new_device_value =
        device_state->provider_requires_roaming() || cellular_allow_roaming_;

    // Only set the value if the current value is different from
    // |new_device_value|.
    if (new_device_value == current_device_value)
      continue;

    SetDevicePropertyInternal(device_state->path(),
                              shill::kCellularAllowRoamingProperty,
                              base::FundamentalValue(new_device_value),
                              base::Bind(&base::DoNothing),
                              network_handler::ErrorCallback());
  }
}

}  // namespace chromeos
<commit_msg>Use shill::kErrorResult* constants.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/network/network_device_handler_impl.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_ipconfig_client.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/shill_property_util.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

std::string GetErrorNameForShillError(const std::string& shill_error_name) {
  if (shill_error_name == shill::kErrorResultFailure)
    return NetworkDeviceHandler::kErrorFailure;
  if (shill_error_name == shill::kErrorResultNotSupported)
    return NetworkDeviceHandler::kErrorNotSupported;
  if (shill_error_name == shill::kErrorResultIncorrectPin)
    return NetworkDeviceHandler::kErrorIncorrectPin;
  if (shill_error_name == shill::kErrorResultPinBlocked)
    return NetworkDeviceHandler::kErrorPinBlocked;
  if (shill_error_name == shill::kErrorResultPinRequired)
    return NetworkDeviceHandler::kErrorPinRequired;
  return NetworkDeviceHandler::kErrorUnknown;
}

void InvokeErrorCallback(const std::string& service_path,
                         const network_handler::ErrorCallback& error_callback,
                         const std::string& error_name) {
  std::string error_msg = "Device Error: " + error_name;
  NET_LOG_ERROR(error_msg, service_path);
  network_handler::RunErrorCallback(
      error_callback, service_path, error_name, error_msg);
}

void HandleShillCallFailure(
    const std::string& device_path,
    const network_handler::ErrorCallback& error_callback,
    const std::string& shill_error_name,
    const std::string& shill_error_message) {
  network_handler::ShillErrorCallbackFunction(
      GetErrorNameForShillError(shill_error_name),
      device_path,
      error_callback,
      shill_error_name,
      shill_error_message);
}

void IPConfigRefreshCallback(const std::string& ipconfig_path,
                             DBusMethodCallStatus call_status) {
  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
    NET_LOG_ERROR(
        base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status),
        ipconfig_path);
  } else {
    NET_LOG_EVENT("IPConfigs.Refresh Succeeded", ipconfig_path);
  }
}

void RefreshIPConfigsCallback(
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback,
    const std::string& device_path,
    const base::DictionaryValue& properties) {
  const base::ListValue* ip_configs;
  if (!properties.GetListWithoutPathExpansion(
          shill::kIPConfigsProperty, &ip_configs)) {
    NET_LOG_ERROR("RequestRefreshIPConfigs Failed", device_path);
    network_handler::ShillErrorCallbackFunction(
        "RequestRefreshIPConfigs Failed",
        device_path,
        error_callback,
        std::string("Missing ") + shill::kIPConfigsProperty, "");
    return;
  }

  for (size_t i = 0; i < ip_configs->GetSize(); i++) {
    std::string ipconfig_path;
    if (!ip_configs->GetString(i, &ipconfig_path))
      continue;
    DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
        dbus::ObjectPath(ipconfig_path),
        base::Bind(&IPConfigRefreshCallback, ipconfig_path));
  }
  // It is safe to invoke |callback| here instead of waiting for the
  // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will
  // be executed in order and thus before any further DBus requests that
  // |callback| may issue.
  if (!callback.is_null())
    callback.Run();
}

void ProposeScanCallback(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback,
    DBusMethodCallStatus call_status) {
  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
    network_handler::ShillErrorCallbackFunction(
        "Device.ProposeScan Failed",
        device_path,
        error_callback,
        base::StringPrintf("DBus call failed: %d", call_status), "");
    return;
  }
  NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path);
  if (!callback.is_null())
    callback.Run();
}

void SetDevicePropertyInternal(
    const std::string& device_path,
    const std::string& property_name,
    const base::Value& value,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
      dbus::ObjectPath(device_path),
      property_name,
      value,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

}  // namespace

NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
  network_state_handler_->RemoveObserver(this, FROM_HERE);
}

void NetworkDeviceHandlerImpl::GetDeviceProperties(
    const std::string& device_path,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback) const {
  DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
      dbus::ObjectPath(device_path),
      base::Bind(&network_handler::GetPropertiesCallback,
                 callback, error_callback, device_path));
}

void NetworkDeviceHandlerImpl::SetDeviceProperty(
    const std::string& device_path,
    const std::string& property_name,
    const base::Value& value,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  const char* const property_blacklist[] = {
      // Must only be changed by policy/owner through.
      shill::kCellularAllowRoamingProperty
  };

  for (size_t i = 0; i < arraysize(property_blacklist); ++i) {
    if (property_name == property_blacklist[i]) {
      InvokeErrorCallback(
          device_path,
          error_callback,
          "SetDeviceProperty called on blacklisted property " + property_name);
      return;
    }
  }

  SetDevicePropertyInternal(
      device_path, property_name, value, callback, error_callback);
}

void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  GetDeviceProperties(device_path,
                      base::Bind(&RefreshIPConfigsCallback,
                                 callback, error_callback),
                      error_callback);
}

void NetworkDeviceHandlerImpl::ProposeScan(
    const std::string& device_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
      dbus::ObjectPath(device_path),
      base::Bind(&ProposeScanCallback, device_path, callback, error_callback));
}

void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
    const std::string& device_path,
    const std::string& network_id,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->Register(
      dbus::ObjectPath(device_path),
      network_id,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::SetCarrier(
    const std::string& device_path,
    const std::string& carrier,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
      dbus::ObjectPath(device_path),
      carrier,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::RequirePin(
    const std::string& device_path,
    bool require_pin,
    const std::string& pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
      dbus::ObjectPath(device_path),
      pin,
      require_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::EnterPin(
    const std::string& device_path,
    const std::string& pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
      dbus::ObjectPath(device_path),
      pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::UnblockPin(
    const std::string& device_path,
    const std::string& puk,
    const std::string& new_pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
      dbus::ObjectPath(device_path),
      puk,
      new_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::ChangePin(
    const std::string& device_path,
    const std::string& old_pin,
    const std::string& new_pin,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
      dbus::ObjectPath(device_path),
      old_pin,
      new_pin,
      callback,
      base::Bind(&HandleShillCallFailure, device_path, error_callback));
}

void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
    const bool allow_roaming) {
  cellular_allow_roaming_ = allow_roaming;
  ApplyCellularAllowRoamingToShill();
}

void NetworkDeviceHandlerImpl::DeviceListChanged() {
  ApplyCellularAllowRoamingToShill();
}

NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
    : network_state_handler_(NULL),
      cellular_allow_roaming_(false) {}

void NetworkDeviceHandlerImpl::Init(
    NetworkStateHandler* network_state_handler) {
  DCHECK(network_state_handler);
  network_state_handler_ = network_state_handler;
  network_state_handler_->AddObserver(this, FROM_HERE);
}

void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
  NetworkStateHandler::DeviceStateList list;
  network_state_handler_->GetDeviceListByType(NetworkTypePattern::Cellular(),
                                              &list);
  if (list.empty()) {
    NET_LOG_DEBUG("No cellular device is available",
                  "Roaming is only supported by cellular devices.");
    return;
  }
  for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin();
      it != list.end(); ++it) {
    const DeviceState* device_state = *it;
    bool current_device_value;
    if (!device_state->properties().GetBooleanWithoutPathExpansion(
             shill::kCellularAllowRoamingProperty, &current_device_value)) {
      NET_LOG_ERROR(
          "Could not get \"allow roaming\" property from cellular "
          "device.",
          device_state->path());
      continue;
    }

    // If roaming is required by the provider, always try to set to true.
    bool new_device_value =
        device_state->provider_requires_roaming() || cellular_allow_roaming_;

    // Only set the value if the current value is different from
    // |new_device_value|.
    if (new_device_value == current_device_value)
      continue;

    SetDevicePropertyInternal(device_state->path(),
                              shill::kCellularAllowRoamingProperty,
                              base::FundamentalValue(new_device_value),
                              base::Bind(&base::DoNothing),
                              network_handler::ErrorCallback());
  }
}

}  // namespace chromeos
<|endoftext|>