<commit_before>/***********************************************************************
	filename: 	CEGUISpinner.cpp
	created:	3/2/2005
	author:		Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/widgets/Spinner.h"
#include "CEGUI/widgets/PushButton.h"
#include "CEGUI/widgets/Editbox.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/WindowManager.h"
#include <stdio.h>
#include <sstream>
#include <iomanip>

// Start of CEGUI namespace section
namespace CEGUI
{
    const String Spinner::WidgetTypeName("CEGUI/Spinner");

    //////////////////////////////////////////////////////////////////////////
    // event strings
    const String Spinner::EventNamespace("Spinner");
    const String Spinner::EventValueChanged("ValueChanged");
    const String Spinner::EventStepChanged("StepChanged");
    const String Spinner::EventMaximumValueChanged("MaximumValueChanged");
    const String Spinner::EventMinimumValueChanged("MinimumValueChanged");
    const String Spinner::EventTextInputModeChanged("TextInputModeChanged");
    // Validator strings
    const String Spinner::FloatValidator("-?\\d*\\.?\\d*");
    const String Spinner::IntegerValidator("-?\\d*");
    const String Spinner::HexValidator("[0-9a-fA-F]*");
    const String Spinner::OctalValidator("[0-7]*");
    // component widget name strings
    const String Spinner::EditboxName( "__auto_editbox__" );
    const String Spinner::IncreaseButtonName( "__auto_incbtn__" );
    const String Spinner::DecreaseButtonName( "__auto_decbtn__" );
    //////////////////////////////////////////////////////////////////////////

    Spinner::Spinner(const String& type, const String& name) :
        Window(type, name),
        d_stepSize(1.0f),
        d_currentValue(1.0f),
        d_maxValue(32767.0f),
        d_minValue(-32768.0f),
        d_inputMode((TextInputMode)-1)
    {
        addSpinnerProperties();
    }

    Spinner::~Spinner(void)
    {
        // Nothing to do here.
    }

    void Spinner::initialiseComponents(void)
    {
        // get all the component widgets
        PushButton* increaseButton = getIncreaseButton();
        PushButton* decreaseButton = getDecreaseButton();
        Editbox* editbox = getEditbox();

        // setup component controls
        increaseButton->setPointerAutoRepeatEnabled(true);
        decreaseButton->setPointerAutoRepeatEnabled(true);

        // perform event subscriptions.
        increaseButton->subscribeEvent(Window::EventPointerPressHold, Event::Subscriber(&Spinner::handleIncreaseButton, this));
        decreaseButton->subscribeEvent(Window::EventPointerPressHold, Event::Subscriber(&Spinner::handleDecreaseButton, this));
        editbox->subscribeEvent(Window::EventTextChanged, Event::Subscriber(&Spinner::handleEditTextChange, this));

        // final initialisation
        setTextInputMode(Integer);
        setCurrentValue(0.0f);
        performChildWindowLayout();
    }

    double Spinner::getCurrentValue(void) const
    {
        return d_currentValue;
    }

    double Spinner::getStepSize(void) const
    {
        return d_stepSize;
    }

    double Spinner::getMaximumValue(void) const
    {
        return d_maxValue;
    }

    double Spinner::getMinimumValue(void) const
    {
        return d_minValue;
    }

    Spinner::TextInputMode Spinner::getTextInputMode(void) const
    {
        return d_inputMode;
    }

    void Spinner::setCurrentValue(double value)
    {
        if (value != d_currentValue)
        {
            // limit input value to within valid range for spinner
            value = ceguimax(ceguimin(value, d_maxValue), d_minValue);

            d_currentValue = value;

            WindowEventArgs args(this);
            onValueChanged(args);
        }
    }

    void Spinner::setStepSize(double step)
    {
        if (step != d_stepSize)
        {
            d_stepSize = step;

            WindowEventArgs args(this);
            onStepChanged(args);
        }
    }

    void Spinner::setMaximumValue(double maxValue)
    {
        if (maxValue != d_maxValue)
        {
            d_maxValue = maxValue;

            WindowEventArgs args(this);
            onMaximumValueChanged(args);
        }
    }

    void Spinner::setMinimumValue(double minVaue)
    {
        if (minVaue != d_minValue)
        {
            d_minValue = minVaue;

            WindowEventArgs args(this);
            onMinimumValueChanged(args);
        }
    }

    void Spinner::setTextInputMode(TextInputMode mode)
    {
        if (mode != d_inputMode)
        {
            switch (mode)
            {
            case FloatingPoint:
                getEditbox()->setValidationString(FloatValidator);
                break;
            case Integer:
                getEditbox()->setValidationString(IntegerValidator);
                break;
            case Hexadecimal:
                getEditbox()->setValidationString(HexValidator);
                break;
            case Octal:
                getEditbox()->setValidationString(OctalValidator);
                break;
            default:
                CEGUI_THROW(InvalidRequestException(
                    "An unknown TextInputMode was specified."));
            }

            d_inputMode = mode;

            WindowEventArgs args(this);
            onTextInputModeChanged(args);
        }
    }

    void Spinner::addSpinnerProperties(void)
    {
        const String& propertyOrigin = WidgetTypeName;

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "CurrentValue", "Property to get/set the current value of the spinner.  Value is a float.",
            &Spinner::setCurrentValue, &Spinner::getCurrentValue, 0.0f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "StepSize", "Property to get/set the step size of the spinner.  Value is a float.",
            &Spinner::setStepSize, &Spinner::getStepSize, 1.0f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "MinimumValue", "Property to get/set the minimum value setting of the spinner.  Value is a float.",
            &Spinner::setMinimumValue, &Spinner::getMinimumValue, -32768.000000f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "MaximumValue", "Property to get/set the maximum value setting of the spinner.  Value is a float.",
            &Spinner::setMaximumValue, &Spinner::getMaximumValue, 32767.000000f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, Spinner::TextInputMode,
            "TextInputMode", "Property to get/set the TextInputMode setting for the spinner.  Value is \"FloatingPoint\", \"Integer\", \"Hexadecimal\", or \"Octal\".",
            &Spinner::setTextInputMode, &Spinner::getTextInputMode, Spinner::Integer
        );
    }

    double Spinner::getValueFromText(void) const
    {
        String tmpTxt(getEditbox()->getText());

        // handle empty and lone '-' or '.' cases
        if (tmpTxt.empty() || (tmpTxt == "-") || (tmpTxt == "."))
        {
            return 0.0f;
        }

        int res, tmp;
        uint utmp;
        double val;

        switch (d_inputMode)
        {
        case FloatingPoint:
            res = sscanf(tmpTxt.c_str(), "%lf", &val);
            break;
        case Integer:
            res = sscanf(tmpTxt.c_str(), "%d", &tmp);
            val = static_cast<double>(tmp);
            break;
        case Hexadecimal:
            res = sscanf(tmpTxt.c_str(), "%x", &utmp);
            val = static_cast<double>(utmp);
            break;
        case Octal:
            res = sscanf(tmpTxt.c_str(), "%o", &utmp);
            val = static_cast<double>(utmp);
            break;
        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown TextInputMode was encountered."));
        }

        if (res)
        {
            return val;
        }

        CEGUI_THROW(InvalidRequestException(
            "The string '" + getEditbox()->getText() +
            "' can not be converted to numerical representation."));
    }

    String Spinner::getTextFromValue(void) const
    {
        std::stringstream tmp;

        switch (d_inputMode)
        {
        case FloatingPoint:
            return CEGUI::PropertyHelper<float>::toString( static_cast<float>(d_currentValue) );
            break;
        case Integer:
            tmp << static_cast<int>(d_currentValue);
            break;
        case Hexadecimal:
            tmp << std::hex << std::uppercase << static_cast<int>(d_currentValue);
            break;
        case Octal:
            tmp << std::oct << static_cast<int>(d_currentValue);
            break;
        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown TextInputMode was encountered."));
        }

        return String(tmp.str().c_str());
    }

    void Spinner::onFontChanged(WindowEventArgs& e)
    {
        // Propagate to children
        getEditbox()->setFont(getFont());
        // Call base class handler
        Window::onFontChanged(e);
    }

    void Spinner::onTextChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();

        // update only if needed
        if (editbox->getText() != getText())
        {
            // done before doing base class processing so event subscribers see
            // 'updated' version.
            editbox->setText(getText());
            ++e.handled;

            Window::onTextChanged(e);
        }
    }

    void Spinner::onActivated(ActivationEventArgs& e)
    {
        if (!isActive())
        {
            Window::onActivated(e);

            Editbox* editbox = getEditbox();

            if (!editbox->isActive())
            {
                editbox->activate();
            }
        }
    }

    void Spinner::onValueChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();

        // mute to save doing unnecessary events work.
        bool wasMuted = editbox->isMuted();
        editbox->setMutedState(true);

        // Update editbox and spinner text with new value.
        // (allow empty and '-' cases to equal 0 with no text change required)
        if (!(d_currentValue == 0 &&
              (editbox->getText().empty() || editbox->getText() == "-")))
        {
            const CEGUI::String& valueString = getTextFromValue();
            editbox->setText(valueString);
            setText(valueString);
        }
        // restore previous mute state.
        editbox->setMutedState(wasMuted);

        fireEvent(EventValueChanged, e, EventNamespace);
    }

    void Spinner::onStepChanged(WindowEventArgs& e)
    {
        fireEvent(EventStepChanged, e, EventNamespace);
    }

    void Spinner::onMaximumValueChanged(WindowEventArgs& e)
    {
        fireEvent(EventMaximumValueChanged, e, EventNamespace);

        if (d_currentValue > d_maxValue)
        {
            setCurrentValue(d_maxValue);
        }
    }

    void Spinner::onMinimumValueChanged(WindowEventArgs& e)
    {
        fireEvent(EventMinimumValueChanged, e, EventNamespace);

        if (d_currentValue < d_minValue)
        {
            setCurrentValue(d_minValue);
        }
    }

    void Spinner::onTextInputModeChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();
        // update edit box text to reflect new mode.
        // mute to save doing unnecessary events work.
        bool wasMuted = editbox->isMuted();
        editbox->setMutedState(true);
        // Update text with new value.
        editbox->setText(getTextFromValue());
        // restore previous mute state.
        editbox->setMutedState(wasMuted);

        fireEvent(EventTextInputModeChanged, e, EventNamespace);
    }

    bool Spinner::handleIncreaseButton(const EventArgs& e)
    {
        if (((const PointerEventArgs&)e).source == PS_Left)
        {
            setCurrentValue(d_currentValue + d_stepSize);
            return true;
        }

        return false;
    }

    bool Spinner::handleDecreaseButton(const EventArgs& e)
    {
        if (((const PointerEventArgs&)e).source == PS_Left)
        {
            setCurrentValue(d_currentValue - d_stepSize);
            return true;
        }

        return false;
    }

    bool Spinner::handleEditTextChange(const EventArgs&)
    {
        // set this windows text to match
        setText(getEditbox()->getText());
        // update value
        setCurrentValue(getValueFromText());
        return true;
    }

    PushButton* Spinner::getIncreaseButton() const
    {
        return static_cast<PushButton*>(getChild(IncreaseButtonName));
    }

    PushButton* Spinner::getDecreaseButton() const
    {
        return static_cast<PushButton*>(getChild(DecreaseButtonName));
    }

    Editbox* Spinner::getEditbox() const
    {
        return static_cast<Editbox*>(getChild(EditboxName));
    }

//////////////////////////////////////////////////////////////////////////

} // End of  CEGUI namespace section
<commit_msg>Backed out changeset: ebcdf16f6207<commit_after>/***********************************************************************
	filename: 	CEGUISpinner.cpp
	created:	3/2/2005
	author:		Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/widgets/Spinner.h"
#include "CEGUI/widgets/PushButton.h"
#include "CEGUI/widgets/Editbox.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/WindowManager.h"
#include <stdio.h>
#include <sstream>
#include <iomanip>

// Start of CEGUI namespace section
namespace CEGUI
{
    const String Spinner::WidgetTypeName("CEGUI/Spinner");

    //////////////////////////////////////////////////////////////////////////
    // event strings
    const String Spinner::EventNamespace("Spinner");
    const String Spinner::EventValueChanged("ValueChanged");
    const String Spinner::EventStepChanged("StepChanged");
    const String Spinner::EventMaximumValueChanged("MaximumValueChanged");
    const String Spinner::EventMinimumValueChanged("MinimumValueChanged");
    const String Spinner::EventTextInputModeChanged("TextInputModeChanged");
    // Validator strings
    const String Spinner::FloatValidator("-?\\d*\\.?\\d*");
    const String Spinner::IntegerValidator("-?\\d*");
    const String Spinner::HexValidator("[0-9a-fA-F]*");
    const String Spinner::OctalValidator("[0-7]*");
    // component widget name strings
    const String Spinner::EditboxName( "__auto_editbox__" );
    const String Spinner::IncreaseButtonName( "__auto_incbtn__" );
    const String Spinner::DecreaseButtonName( "__auto_decbtn__" );
    //////////////////////////////////////////////////////////////////////////

    Spinner::Spinner(const String& type, const String& name) :
        Window(type, name),
        d_stepSize(1.0f),
        d_currentValue(1.0f),
        d_maxValue(32767.0f),
        d_minValue(-32768.0f),
        d_inputMode((TextInputMode)-1)
    {
        addSpinnerProperties();
    }

    Spinner::~Spinner(void)
    {
        // Nothing to do here.
    }

    void Spinner::initialiseComponents(void)
    {
        // get all the component widgets
        PushButton* increaseButton = getIncreaseButton();
        PushButton* decreaseButton = getDecreaseButton();
        Editbox* editbox = getEditbox();

        // setup component controls
        increaseButton->setPointerAutoRepeatEnabled(true);
        decreaseButton->setPointerAutoRepeatEnabled(true);

        // perform event subscriptions.
        increaseButton->subscribeEvent(Window::EventPointerPressHold, Event::Subscriber(&Spinner::handleIncreaseButton, this));
        decreaseButton->subscribeEvent(Window::EventPointerPressHold, Event::Subscriber(&Spinner::handleDecreaseButton, this));
        editbox->subscribeEvent(Window::EventTextChanged, Event::Subscriber(&Spinner::handleEditTextChange, this));

        // final initialisation
        setTextInputMode(Integer);
        setCurrentValue(0.0f);
        performChildWindowLayout();
    }

    double Spinner::getCurrentValue(void) const
    {
        return d_currentValue;
    }

    double Spinner::getStepSize(void) const
    {
        return d_stepSize;
    }

    double Spinner::getMaximumValue(void) const
    {
        return d_maxValue;
    }

    double Spinner::getMinimumValue(void) const
    {
        return d_minValue;
    }

    Spinner::TextInputMode Spinner::getTextInputMode(void) const
    {
        return d_inputMode;
    }

    void Spinner::setCurrentValue(double value)
    {
        if (value != d_currentValue)
        {
            // limit input value to within valid range for spinner
            value = ceguimax(ceguimin(value, d_maxValue), d_minValue);

            d_currentValue = value;

            WindowEventArgs args(this);
            onValueChanged(args);
        }
    }

    void Spinner::setStepSize(double step)
    {
        if (step != d_stepSize)
        {
            d_stepSize = step;

            WindowEventArgs args(this);
            onStepChanged(args);
        }
    }

    void Spinner::setMaximumValue(double maxValue)
    {
        if (maxValue != d_maxValue)
        {
            d_maxValue = maxValue;

            WindowEventArgs args(this);
            onMaximumValueChanged(args);
        }
    }

    void Spinner::setMinimumValue(double minVaue)
    {
        if (minVaue != d_minValue)
        {
            d_minValue = minVaue;

            WindowEventArgs args(this);
            onMinimumValueChanged(args);
        }
    }

    void Spinner::setTextInputMode(TextInputMode mode)
    {
        if (mode != d_inputMode)
        {
            switch (mode)
            {
            case FloatingPoint:
                getEditbox()->setValidationString(FloatValidator);
                break;
            case Integer:
                getEditbox()->setValidationString(IntegerValidator);
                break;
            case Hexadecimal:
                getEditbox()->setValidationString(HexValidator);
                break;
            case Octal:
                getEditbox()->setValidationString(OctalValidator);
                break;
            default:
                CEGUI_THROW(InvalidRequestException(
                    "An unknown TextInputMode was specified."));
            }

            d_inputMode = mode;

            WindowEventArgs args(this);
            onTextInputModeChanged(args);
        }
    }

    void Spinner::addSpinnerProperties(void)
    {
        const String& propertyOrigin = WidgetTypeName;

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "CurrentValue", "Property to get/set the current value of the spinner.  Value is a float.",
            &Spinner::setCurrentValue, &Spinner::getCurrentValue, 0.0f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "StepSize", "Property to get/set the step size of the spinner.  Value is a float.",
            &Spinner::setStepSize, &Spinner::getStepSize, 1.0f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "MinimumValue", "Property to get/set the minimum value setting of the spinner.  Value is a float.",
            &Spinner::setMinimumValue, &Spinner::getMinimumValue, -32768.000000f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, double,
            "MaximumValue", "Property to get/set the maximum value setting of the spinner.  Value is a float.",
            &Spinner::setMaximumValue, &Spinner::getMaximumValue, 32767.000000f
        );

        CEGUI_DEFINE_PROPERTY(Spinner, Spinner::TextInputMode,
            "TextInputMode", "Property to get/set the TextInputMode setting for the spinner.  Value is \"FloatingPoint\", \"Integer\", \"Hexadecimal\", or \"Octal\".",
            &Spinner::setTextInputMode, &Spinner::getTextInputMode, Spinner::Integer
        );
    }

    double Spinner::getValueFromText(void) const
    {
        String tmpTxt(getEditbox()->getText());

        // handle empty and lone '-' or '.' cases
        if (tmpTxt.empty() || (tmpTxt == "-") || (tmpTxt == "."))
        {
            return 0.0f;
        }

        int res, tmp;
        uint utmp;
        double val;

        switch (d_inputMode)
        {
        case FloatingPoint:
            res = sscanf(tmpTxt.c_str(), "%lf", &val);
            break;
        case Integer:
            res = sscanf(tmpTxt.c_str(), "%d", &tmp);
            val = static_cast<double>(tmp);
            break;
        case Hexadecimal:
            res = sscanf(tmpTxt.c_str(), "%x", &utmp);
            val = static_cast<double>(utmp);
            break;
        case Octal:
            res = sscanf(tmpTxt.c_str(), "%o", &utmp);
            val = static_cast<double>(utmp);
            break;
        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown TextInputMode was encountered."));
        }

        if (res)
        {
            return val;
        }

        CEGUI_THROW(InvalidRequestException(
            "The string '" + getEditbox()->getText() +
            "' can not be converted to numerical representation."));
    }

    String Spinner::getTextFromValue(void) const
    {
        std::stringstream tmp;

        switch (d_inputMode)
        {
        case FloatingPoint:
            return CEGUI::PropertyHelper<float>::toString( static_cast<float>(d_currentValue) );
            break;
        case Integer:
            tmp << static_cast<int>(d_currentValue);
            break;
        case Hexadecimal:
            tmp << std::hex << std::uppercase << static_cast<int>(d_currentValue);
            break;
        case Octal:
            tmp << std::oct << static_cast<int>(d_currentValue);
            break;
        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown TextInputMode was encountered."));
        }

        return String(tmp.str().c_str());
    }

    void Spinner::onFontChanged(WindowEventArgs& e)
    {
        // Propagate to children
        getEditbox()->setFont(getFont());
        // Call base class handler
        Window::onFontChanged(e);
    }

    void Spinner::onTextChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();

        // update only if needed
        if (editbox->getText() != getText())
        {
            // done before doing base class processing so event subscribers see
            // 'updated' version.
            editbox->setText(getText());
            ++e.handled;

            Window::onTextChanged(e);
        }
    }

    void Spinner::onActivated(ActivationEventArgs& e)
    {
        if (!isActive())
        {
            Window::onActivated(e);

            Editbox* editbox = getEditbox();

            if (!editbox->isActive())
            {
                editbox->activate();
            }
        }
    }

    void Spinner::onValueChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();

        // mute to save doing unnecessary events work.
        bool wasMuted = editbox->isMuted();
        editbox->setMutedState(true);

        // Update text with new value.
        // (allow empty and '-' cases to equal 0 with no text change required)
        if (!(d_currentValue == 0 &&
              (editbox->getText().empty() || editbox->getText() == "-")))
        {
            editbox->setText(getTextFromValue());
        }
        // restore previous mute state.
        editbox->setMutedState(wasMuted);

        fireEvent(EventValueChanged, e, EventNamespace);
    }

    void Spinner::onStepChanged(WindowEventArgs& e)
    {
        fireEvent(EventStepChanged, e, EventNamespace);
    }

    void Spinner::onMaximumValueChanged(WindowEventArgs& e)
    {
        fireEvent(EventMaximumValueChanged, e, EventNamespace);

        if (d_currentValue > d_maxValue)
        {
            setCurrentValue(d_maxValue);
        }
    }

    void Spinner::onMinimumValueChanged(WindowEventArgs& e)
    {
        fireEvent(EventMinimumValueChanged, e, EventNamespace);

        if (d_currentValue < d_minValue)
        {
            setCurrentValue(d_minValue);
        }
    }

    void Spinner::onTextInputModeChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();
        // update edit box text to reflect new mode.
        // mute to save doing unnecessary events work.
        bool wasMuted = editbox->isMuted();
        editbox->setMutedState(true);
        // Update text with new value.
        editbox->setText(getTextFromValue());
        // restore previous mute state.
        editbox->setMutedState(wasMuted);

        fireEvent(EventTextInputModeChanged, e, EventNamespace);
    }

    bool Spinner::handleIncreaseButton(const EventArgs& e)
    {
        if (((const PointerEventArgs&)e).source == PS_Left)
        {
            setCurrentValue(d_currentValue + d_stepSize);
            return true;
        }

        return false;
    }

    bool Spinner::handleDecreaseButton(const EventArgs& e)
    {
        if (((const PointerEventArgs&)e).source == PS_Left)
        {
            setCurrentValue(d_currentValue - d_stepSize);
            return true;
        }

        return false;
    }

    bool Spinner::handleEditTextChange(const EventArgs&)
    {
        // set this windows text to match
        setText(getEditbox()->getText());
        // update value
        setCurrentValue(getValueFromText());
        return true;
    }

    PushButton* Spinner::getIncreaseButton() const
    {
        return static_cast<PushButton*>(getChild(IncreaseButtonName));
    }

    PushButton* Spinner::getDecreaseButton() const
    {
        return static_cast<PushButton*>(getChild(DecreaseButtonName));
    }

    Editbox* Spinner::getEditbox() const
    {
        return static_cast<Editbox*>(getChild(EditboxName));
    }

//////////////////////////////////////////////////////////////////////////

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>#include "../USB.h"
#include "../configuration.h"
#include "../deviceproxy.h"
#include "../usb-pad/padproxy.h"
#include "../usb-mic/audiosourceproxy.h"

#include <sstream>
#include <map>
#include <vector>
#include <string>

#include "ini.h"
#include "config.h"

//libjoyrumble used as an example
//Hopefully PCSX2 has inited all the GTK stuff already
using namespace std;

static std::string usb_path;
std::string IniDir;
std::string LogDir;
const char* iniFile = "USBqemu-wheel.ini";

void SysMessage(const char *fmt, ...)
{
	va_list arglist;

	va_start(arglist, fmt);
	vfprintf(stderr, fmt, arglist);
	va_end(arglist);
}

void CALLBACK USBsetSettingsDir( const char* dir )
{
	fprintf(stderr, "USBsetSettingsDir: %s\n", dir);
	IniDir = dir;
}

void CALLBACK USBsetLogDir( const char* dir )
{
	printf("USBsetLogDir: %s\n", dir);
	LogDir = dir;
}

bool LoadSettingValue(const std::string& ini, const std::string& section, const char* param, std::string& value)
{
	char tmp[4096] = {0};
	if (INILoadString(ini.c_str(), section.c_str(), param, tmp) != 0)
		return false;

	value = tmp;
	return true;
}

bool LoadSettingValue(const std::string& ini, const std::string& section, const char* param, int32_t& value)
{
	return INILoadUInt(ini.c_str(), section.c_str(), param, (unsigned int *)&value) == 0;
}

bool SaveSettingValue(const std::string& ini, const std::string& section, const char* param, std::string& value)
{
	return INISaveString(ini.c_str(), section.c_str(), param, value.c_str()) == 0;
}

bool SaveSettingValue(const std::string& ini, const std::string& section, const char* param, int32_t& value)
{
	return INISaveUInt(ini.c_str(), section.c_str(), param, (unsigned int)value) == 0;
}

bool LoadSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	fprintf(stderr, "USBqemu load \"%s\" from [%s %d]\n", var.name, key.c_str(), port);

	if (key.empty())
		return false;

	std::stringstream section;
	section << key << " " << port;

	std::string ini(IniDir);
	ini.append(iniFile);

	switch(var.type)
	{
		case CONFIG_TYPE_INT:
			return LoadSettingValue(ini, section.str(), var.name, var.intValue);
		//case CONFIG_TYPE_DOUBLE:
		//	return LoadSettingValue(ini, section.str(), var.name, var.doubleValue);
		case CONFIG_TYPE_TCHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.tstrValue);
		case CONFIG_TYPE_CHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.strValue);
		//case CONFIG_TYPE_WCHAR:
		//	return LoadSettingValue(ini, section.str(), var.name, var.wstrValue);
		break;
		default:
			fprintf(stderr, "Invalid config type %d for %s\n", var.type, var.name);
			break;
	};
	return false;
}

/**
 *
 * [devices]
 * portX = pad
 *
 * [pad X]
 * api = joydev
 *
 * [joydev X]
 * button0 = 1
 * button1 = 2
 * ...
 *
 * */
bool SaveSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	fprintf(stderr, "USBqemu save \"%s\" to [%s %d]\n", var.name, key.c_str(), port);

	if (key.empty())
		return false;

	std::stringstream section;
	section << key << " " << port;

	std::string ini(IniDir);
	ini.append(iniFile);

	switch(var.type)
	{
		case CONFIG_TYPE_INT:
			return SaveSettingValue(ini, section.str(), var.name, var.intValue);
		case CONFIG_TYPE_TCHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.tstrValue);
		case CONFIG_TYPE_CHAR:
			return SaveSettingValue(ini, section.str(), var.name, var.strValue);
		break;
		default:
			fprintf(stderr, "Invalid config type %d for %s\n", var.type, var.name);
			break;
	};
	return false;
}

void SaveConfig() {
	fprintf(stderr, "USB save config\n");
	//char* envptr = getenv("HOME");
	//if(envptr == NULL)
	//	return;
	//char path[1024];
	//snprintf(path, sizeof(path), "%s/.config/PCSX2/inis/USBqemu-wheel.ini", envptr);
	std::string iniPath(IniDir);
	iniPath.append(iniFile);
	const char *path = iniPath.c_str();

	//fprintf(stderr, "%s\n", path);

	INISaveString(path, N_DEVICES, N_DEVICE_PORT0, conf.Port0.c_str());
	INISaveString(path, N_DEVICES, N_DEVICE_PORT1, conf.Port1.c_str());
	INISaveUInt(path, N_DEVICES, N_WHEEL_TYPE0, conf.WheelType[0]);
	INISaveUInt(path, N_DEVICES, N_WHEEL_TYPE1, conf.WheelType[1]);

	for (auto& k : changedAPIs)
	{
		CONFIGVARIANT var(N_DEVICE_API, CONFIG_TYPE_CHAR);
		var.strValue = k.second;
		fprintf(stderr, "Save apis: %s %s\n", k.first.second.c_str(), k.second.c_str());
		SaveSetting(k.first.first, k.first.second, var);
	}
}

void LoadConfig() {
	char tmp[1024] = {0};
	fprintf(stderr, "USB load config\n");
	//char* envptr = getenv("HOME");
	//if(envptr == NULL)
	//	return;
	//char path[1024];
	//sprintf(path, "%s/.config/PCSX2/inis/USBqemu-wheel.ini", envptr);
	std::string iniPath(IniDir);
	iniPath.append(iniFile);
	const char *path = iniPath.c_str();

	INILoadString(path, N_DEVICES, N_DEVICE_PORT0, tmp);
	conf.Port0 = tmp;
	INILoadString(path, N_DEVICES, N_DEVICE_PORT1, tmp);
	conf.Port1 = tmp;
	INILoadUInt(path, N_DEVICES, N_WHEEL_TYPE0, (u32*)&conf.WheelType[0]);
	INILoadUInt(path, N_DEVICES, N_WHEEL_TYPE1, (u32*)&conf.WheelType[1]);

	{
		auto instance = RegisterDevice::instance();
		CONFIGVARIANT tmpVar(N_DEVICE_API, CONFIG_TYPE_CHAR);
		LoadSetting(0, conf.Port0, tmpVar);
		std::string api = tmpVar.strValue;
		auto dev = instance.Device(conf.Port0);

		if (dev && !dev->IsValidAPI(api))
		{
			auto apis = dev->APIs();
			if (!apis.empty())
				api = *apis.begin();
		}

		if(api.size())
			changedAPIs[std::make_pair(0, conf.Port0)] = api;

		LoadSetting(1, conf.Port1, tmpVar);
		api = tmpVar.strValue;

		dev = instance.Device(conf.Port1);
		if (dev && !dev->IsValidAPI(api))
		{
			auto apis = dev->APIs();
			if (!apis.empty())
				api = *apis.begin();
		}

		if(api.size())
			changedAPIs[std::make_pair(1, conf.Port1)] = api;
	}
}
<commit_msg>linux/config: remove log/ini path logging<commit_after>#include "../USB.h"
#include "../configuration.h"
#include "../deviceproxy.h"
#include "../usb-pad/padproxy.h"
#include "../usb-mic/audiosourceproxy.h"

#include <sstream>
#include <map>
#include <vector>
#include <string>

#include "ini.h"
#include "config.h"

//libjoyrumble used as an example
//Hopefully PCSX2 has inited all the GTK stuff already
using namespace std;

static std::string usb_path;
std::string IniDir;
std::string LogDir;
const char* iniFile = "USBqemu-wheel.ini";

void SysMessage(const char *fmt, ...)
{
	va_list arglist;

	va_start(arglist, fmt);
	vfprintf(stderr, fmt, arglist);
	va_end(arglist);
}

void CALLBACK USBsetSettingsDir( const char* dir )
{
	IniDir = dir;
}

void CALLBACK USBsetLogDir( const char* dir )
{
	LogDir = dir;
}

bool LoadSettingValue(const std::string& ini, const std::string& section, const char* param, std::string& value)
{
	char tmp[4096] = {0};
	if (INILoadString(ini.c_str(), section.c_str(), param, tmp) != 0)
		return false;

	value = tmp;
	return true;
}

bool LoadSettingValue(const std::string& ini, const std::string& section, const char* param, int32_t& value)
{
	return INILoadUInt(ini.c_str(), section.c_str(), param, (unsigned int *)&value) == 0;
}

bool SaveSettingValue(const std::string& ini, const std::string& section, const char* param, std::string& value)
{
	return INISaveString(ini.c_str(), section.c_str(), param, value.c_str()) == 0;
}

bool SaveSettingValue(const std::string& ini, const std::string& section, const char* param, int32_t& value)
{
	return INISaveUInt(ini.c_str(), section.c_str(), param, (unsigned int)value) == 0;
}

bool LoadSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	fprintf(stderr, "USBqemu load \"%s\" from [%s %d]\n", var.name, key.c_str(), port);

	if (key.empty())
		return false;

	std::stringstream section;
	section << key << " " << port;

	std::string ini(IniDir);
	ini.append(iniFile);

	switch(var.type)
	{
		case CONFIG_TYPE_INT:
			return LoadSettingValue(ini, section.str(), var.name, var.intValue);
		//case CONFIG_TYPE_DOUBLE:
		//	return LoadSettingValue(ini, section.str(), var.name, var.doubleValue);
		case CONFIG_TYPE_TCHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.tstrValue);
		case CONFIG_TYPE_CHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.strValue);
		//case CONFIG_TYPE_WCHAR:
		//	return LoadSettingValue(ini, section.str(), var.name, var.wstrValue);
		break;
		default:
			fprintf(stderr, "Invalid config type %d for %s\n", var.type, var.name);
			break;
	};
	return false;
}

/**
 *
 * [devices]
 * portX = pad
 *
 * [pad X]
 * api = joydev
 *
 * [joydev X]
 * button0 = 1
 * button1 = 2
 * ...
 *
 * */
bool SaveSetting(int port, const std::string& key, CONFIGVARIANT& var)
{
	fprintf(stderr, "USBqemu save \"%s\" to [%s %d]\n", var.name, key.c_str(), port);

	if (key.empty())
		return false;

	std::stringstream section;
	section << key << " " << port;

	std::string ini(IniDir);
	ini.append(iniFile);

	switch(var.type)
	{
		case CONFIG_TYPE_INT:
			return SaveSettingValue(ini, section.str(), var.name, var.intValue);
		case CONFIG_TYPE_TCHAR:
			return LoadSettingValue(ini, section.str(), var.name, var.tstrValue);
		case CONFIG_TYPE_CHAR:
			return SaveSettingValue(ini, section.str(), var.name, var.strValue);
		break;
		default:
			fprintf(stderr, "Invalid config type %d for %s\n", var.type, var.name);
			break;
	};
	return false;
}

void SaveConfig() {
	fprintf(stderr, "USB save config\n");
	//char* envptr = getenv("HOME");
	//if(envptr == NULL)
	//	return;
	//char path[1024];
	//snprintf(path, sizeof(path), "%s/.config/PCSX2/inis/USBqemu-wheel.ini", envptr);
	std::string iniPath(IniDir);
	iniPath.append(iniFile);
	const char *path = iniPath.c_str();

	//fprintf(stderr, "%s\n", path);

	INISaveString(path, N_DEVICES, N_DEVICE_PORT0, conf.Port0.c_str());
	INISaveString(path, N_DEVICES, N_DEVICE_PORT1, conf.Port1.c_str());
	INISaveUInt(path, N_DEVICES, N_WHEEL_TYPE0, conf.WheelType[0]);
	INISaveUInt(path, N_DEVICES, N_WHEEL_TYPE1, conf.WheelType[1]);

	for (auto& k : changedAPIs)
	{
		CONFIGVARIANT var(N_DEVICE_API, CONFIG_TYPE_CHAR);
		var.strValue = k.second;
		fprintf(stderr, "Save apis: %s %s\n", k.first.second.c_str(), k.second.c_str());
		SaveSetting(k.first.first, k.first.second, var);
	}
}

void LoadConfig() {
	char tmp[1024] = {0};
	fprintf(stderr, "USB load config\n");
	//char* envptr = getenv("HOME");
	//if(envptr == NULL)
	//	return;
	//char path[1024];
	//sprintf(path, "%s/.config/PCSX2/inis/USBqemu-wheel.ini", envptr);
	std::string iniPath(IniDir);
	iniPath.append(iniFile);
	const char *path = iniPath.c_str();

	INILoadString(path, N_DEVICES, N_DEVICE_PORT0, tmp);
	conf.Port0 = tmp;
	INILoadString(path, N_DEVICES, N_DEVICE_PORT1, tmp);
	conf.Port1 = tmp;
	INILoadUInt(path, N_DEVICES, N_WHEEL_TYPE0, (u32*)&conf.WheelType[0]);
	INILoadUInt(path, N_DEVICES, N_WHEEL_TYPE1, (u32*)&conf.WheelType[1]);

	{
		auto instance = RegisterDevice::instance();
		CONFIGVARIANT tmpVar(N_DEVICE_API, CONFIG_TYPE_CHAR);
		LoadSetting(0, conf.Port0, tmpVar);
		std::string api = tmpVar.strValue;
		auto dev = instance.Device(conf.Port0);

		if (dev && !dev->IsValidAPI(api))
		{
			auto apis = dev->APIs();
			if (!apis.empty())
				api = *apis.begin();
		}

		if(api.size())
			changedAPIs[std::make_pair(0, conf.Port0)] = api;

		LoadSetting(1, conf.Port1, tmpVar);
		api = tmpVar.strValue;

		dev = instance.Device(conf.Port1);
		if (dev && !dev->IsValidAPI(api))
		{
			auto apis = dev->APIs();
			if (!apis.empty())
				api = *apis.begin();
		}

		if(api.size())
			changedAPIs[std::make_pair(1, conf.Port1)] = api;
	}
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <string>
#include <regex>
#include <fstream>
#include <sys/stat.h>
#include <Foundation/Foundation.h>
// http://tclap.sourceforge.net/manual.html
#include "tclap/CmdLine.h"
#include "HCIDumpParser.h"

static HCIDumpParser parserLogic;

#define STOP_MARKER_FILE "STOP"

inline bool stopMarkerExists() {
    struct stat buffer;
    bool stop = (stat (STOP_MARKER_FILE, &buffer) == 0);
    if(stop) {
        printf("Found STOP marker file, will exit...\n");
    }
    return stop;
}
static long eventCount = 0;
static long lastMarkerCheckTime = 0;

extern "C" bool beacon_event_callback(const beacon_info *info) {
    //printf("beacon_event_callback(%s, code=%d)\n", info->uuid, info->code);
    parserLogic.beaconEvent(info);
    eventCount ++;
    // Check for a termination marker every 1000 events or 5 seconds
    bool stop = false;
    long elapsed = info->time - lastMarkerCheckTime;
    if((eventCount % 1000) == 0 || elapsed > 5000) {
        lastMarkerCheckTime = info->time;
        stop = stopMarkerExists();
    }
    return stop;
}

using namespace std;

/**
* A version of the native scanner that directly integrates with the bluez stack hcidump command rather than parsing
* the hcidump output.
*/
int main(int argc, const char **argv) {

    printf("NativeScanner starting up...\n");
    TCLAP::CmdLine cmd("NativeScanner command line options", ' ', "0.1");
    //
    TCLAP::ValueArg<std::string> scannerID("s", "scannerID",
            "Specify the ID of the scanner generating the beacon events",
            true, "DEFAULT", "string", cmd);
    TCLAP::ValueArg<std::string> rawDumpFile("d", "rawDumpFile",
            "Specify a path to an hcidump file to parse for testing",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> clientID("c", "clientID",
            "Specify the clientID to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> username("u", "username",
            "Specify the username to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> password("p", "password",
            "Specify the password to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> brokerURL("b", "brokerURL",
            "Specify the brokerURL to connect to the MQTT broker with; default tcp://localhost:1883",
            false, "tcp://localhost:1883", "string", cmd);
    TCLAP::ValueArg<std::string> topicName("t", "topicName",
            "Specify the name of the queue on the MQTT broker to publish to; default beaconEvents",
            false, "beaconEvents", "string", cmd);
    TCLAP::SwitchArg skipPublish("S", "skipPublish",
            "Indicate that the parsed beacons should not be published",
            false);
    TCLAP::SwitchArg asyncMode("A", "asyncMode",
            "Indicate that the parsed beacons should be published using async delivery mode",
            false);
    TCLAP::ValueArg<std::string> hciDev("D", "hciDev",
            "Specify the name of the host controller interface to use; default hci0",
            false, "hci0", "string", cmd);
    try {
        // Add the flag arguments
        cmd.add(skipPublish);
        cmd.add(asyncMode);
        // Parse the argv array.
        printf("Parsing command line...\n");
        cmd.parse( argc, argv );
        printf("done\n");
    }
    catch (TCLAP::ArgException &e) {
        fprintf(stderr, "error: %s for arg: %s\n", e.error().c_str(), e.argId().c_str());
    }

    // Remove any stop marker file
    if(remove(STOP_MARKER_FILE) == 0) {
        printf("Removed existing %s marker file\n", STOP_MARKER_FILE);
    }

    HCIDumpCommand command(scannerID.getValue(), brokerURL.getValue(), clientID.getValue(), topicName.getValue());
    command.setSkipPublish(skipPublish.getValue());
    command.setHciDev(hciDev.getValue());
    command.setAsyncMode(asyncMode.getValue());
    printf("Begin scanning...\n");
    parserLogic.processHCI(command);
    parserLogic.cleanup();
    printf("End scanning\n");
    return 0;
}
<commit_msg>Remove the spurious osx include<commit_after>#include <cstdio>
#include <string>
#include <regex>
#include <fstream>
#include <sys/stat.h>
// http://tclap.sourceforge.net/manual.html
#include "tclap/CmdLine.h"
#include "HCIDumpParser.h"

static HCIDumpParser parserLogic;

#define STOP_MARKER_FILE "STOP"

inline bool stopMarkerExists() {
    struct stat buffer;
    bool stop = (stat (STOP_MARKER_FILE, &buffer) == 0);
    if(stop) {
        printf("Found STOP marker file, will exit...\n");
    }
    return stop;
}
static long eventCount = 0;
static long lastMarkerCheckTime = 0;

extern "C" bool beacon_event_callback(const beacon_info *info) {
    //printf("beacon_event_callback(%s, code=%d)\n", info->uuid, info->code);
    parserLogic.beaconEvent(info);
    eventCount ++;
    // Check for a termination marker every 1000 events or 5 seconds
    bool stop = false;
    long elapsed = info->time - lastMarkerCheckTime;
    if((eventCount % 1000) == 0 || elapsed > 5000) {
        lastMarkerCheckTime = info->time;
        stop = stopMarkerExists();
    }
    return stop;
}

using namespace std;

/**
* A version of the native scanner that directly integrates with the bluez stack hcidump command rather than parsing
* the hcidump output.
*/
int main(int argc, const char **argv) {

    printf("NativeScanner starting up...\n");
    TCLAP::CmdLine cmd("NativeScanner command line options", ' ', "0.1");
    //
    TCLAP::ValueArg<std::string> scannerID("s", "scannerID",
            "Specify the ID of the scanner generating the beacon events",
            true, "DEFAULT", "string", cmd);
    TCLAP::ValueArg<std::string> rawDumpFile("d", "rawDumpFile",
            "Specify a path to an hcidump file to parse for testing",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> clientID("c", "clientID",
            "Specify the clientID to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> username("u", "username",
            "Specify the username to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> password("p", "password",
            "Specify the password to connect to the MQTT broker with",
            false, "", "string", cmd);
    TCLAP::ValueArg<std::string> brokerURL("b", "brokerURL",
            "Specify the brokerURL to connect to the MQTT broker with; default tcp://localhost:1883",
            false, "tcp://localhost:1883", "string", cmd);
    TCLAP::ValueArg<std::string> topicName("t", "topicName",
            "Specify the name of the queue on the MQTT broker to publish to; default beaconEvents",
            false, "beaconEvents", "string", cmd);
    TCLAP::SwitchArg skipPublish("S", "skipPublish",
            "Indicate that the parsed beacons should not be published",
            false);
    TCLAP::SwitchArg asyncMode("A", "asyncMode",
            "Indicate that the parsed beacons should be published using async delivery mode",
            false);
    TCLAP::ValueArg<std::string> hciDev("D", "hciDev",
            "Specify the name of the host controller interface to use; default hci0",
            false, "hci0", "string", cmd);
    try {
        // Add the flag arguments
        cmd.add(skipPublish);
        cmd.add(asyncMode);
        // Parse the argv array.
        printf("Parsing command line...\n");
        cmd.parse( argc, argv );
        printf("done\n");
    }
    catch (TCLAP::ArgException &e) {
        fprintf(stderr, "error: %s for arg: %s\n", e.error().c_str(), e.argId().c_str());
    }

    // Remove any stop marker file
    if(remove(STOP_MARKER_FILE) == 0) {
        printf("Removed existing %s marker file\n", STOP_MARKER_FILE);
    }

    HCIDumpCommand command(scannerID.getValue(), brokerURL.getValue(), clientID.getValue(), topicName.getValue());
    command.setSkipPublish(skipPublish.getValue());
    command.setHciDev(hciDev.getValue());
    command.setAsyncMode(asyncMode.getValue());
    printf("Begin scanning...\n");
    parserLogic.processHCI(command);
    parserLogic.cleanup();
    printf("End scanning\n");
    return 0;
}
<|endoftext|>


<commit_before>// 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.

// TODO(port): the ifdefs in here are a first step towards trying to determine
// the correct abstraction for all the OS functionality required at this
// stage of process initialization. It should not be taken as a final
// abstraction.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <algorithm>
#include <atlbase.h>
#include <atlapp.h>
#include <malloc.h>
#include <new.h>
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug_util.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#if defined(OS_WIN)
#include "base/win_util.h"
#endif
#include "chrome/app/scoped_ole_initializer.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/sandbox_init_wrapper.h"
#if defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#include "tools/memory_watcher/memory_watcher.h"
#endif
#if defined(OS_MACOSX)
#include "third_party/WebKit/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
#endif

extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);

#if defined(OS_WIN)
// TODO(erikkay): isn't this already defined somewhere?
#define DLLEXPORT __declspec(dllexport)

// We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
extern "C" {
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line);
}
#elif defined(OS_POSIX)
extern "C" {
int ChromeMain(int argc, const char** argv);
}
#endif

namespace {

#if defined(OS_WIN)
const wchar_t kProfilingDll[] = L"memory_watcher.dll";

// Load the memory profiling DLL.  All it needs to be activated
// is to be loaded.  Return true on success, false otherwise.
bool LoadMemoryProfiler() {
  HMODULE prof_module = LoadLibrary(kProfilingDll);
  return prof_module != NULL;
}

CAppModule _Module;

#pragma optimize("", off)
// Handlers for invalid parameter and pure call. They generate a breakpoint to
// tell breakpad that it needs to dump the process.
void InvalidParameter(const wchar_t* expression, const wchar_t* function,
                      const wchar_t* file, unsigned int line,
                      uintptr_t reserved) {
  __debugbreak();
}

void PureCall() {
  __debugbreak();
}

int OnNoMemory(size_t memory_size) {
  __debugbreak();
  // Return memory_size so it is not optimized out. Make sure the return value
  // is at least 1 so malloc/new is retried, especially useful when under a
  // debugger.
  return memory_size ? static_cast<int>(memory_size) : 1;
}

// Handlers to silently dump the current process when there is an assert in
// chrome.
void ChromeAssert(const std::string& str) {
  // Get the breakpad pointer from chrome.exe
  typedef void (__stdcall *DumpProcessFunction)();
  DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
      ::GetProcAddress(::GetModuleHandle(L"chrome.exe"), "DumpProcess"));
  if (DumpProcess)
    DumpProcess();
}

#pragma optimize("", on)

// Early versions of Chrome incorrectly registered a chromehtml: URL handler.
// Later versions fixed the registration but in some cases (e.g. Vista and non-
// admin installs) the fix could not be applied.  This prevents Chrome to be
// launched with the incorrect format.
// CORRECT: <broser.exe> -- "chromehtml:<url>"
// INVALID: <broser.exe> "chromehtml:<url>"
bool IncorrectChromeHtmlArguments(const std::wstring& command_line) {
  const wchar_t kChromeHtml[] = L"-- \"chromehtml:";
  const wchar_t kOffset = 5;  // Where chromehtml: starts in above
  std::wstring command_line_lower = command_line;

  // We are only searching for ASCII characters so this is OK.
  StringToLowerASCII(&command_line_lower);

  std::wstring::size_type pos = command_line_lower.find(
      kChromeHtml + kOffset);

  if (pos == std::wstring::npos)
    return false;

  // The browser is being launched with chromehtml: somewhere on the command
  // line.  We will not launch unless it's preceded by the -- switch terminator.
  if (pos >= kOffset) {
    if (equal(kChromeHtml, kChromeHtml + arraysize(kChromeHtml) - 1,
        command_line_lower.begin() + pos - kOffset)) {
      return false;
    }
  }

  return true;
}

#endif  // OS_WIN

// Register the invalid param handler and pure call handler to be able to
// notify breakpad when it happens.
void RegisterInvalidParamHandler() {
#if defined(OS_WIN)
  _set_invalid_parameter_handler(InvalidParameter);
  _set_purecall_handler(PureCall);
  // Gather allocation failure.
  _set_new_handler(&OnNoMemory);
  // Make sure malloc() calls the new handler too.
  _set_new_mode(1);
#endif
}

void SetupCRT(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#else
  if (!parsed_command_line.HasSwitch(switches::kDisableBreakpad)) {
    _CrtSetReportMode(_CRT_ASSERT, 0);
  }
#endif

  // Enable the low fragmentation heap for the CRT heap. The heap is not changed
  // if the process is run under the debugger is enabled or if certain gflags
  // are set.
  bool use_lfh = false;
  if (parsed_command_line.HasSwitch(switches::kUseLowFragHeapCrt))
    use_lfh = parsed_command_line.GetSwitchValue(switches::kUseLowFragHeapCrt)
        != L"false";
  if (use_lfh) {
    void* crt_heap = reinterpret_cast<void*>(_get_heap_handle());
    ULONG enable_lfh = 2;
    HeapSetInformation(crt_heap, HeapCompatibilityInformation,
                       &enable_lfh, sizeof(enable_lfh));
  }
#endif
}

// Enable the heap profiler if the appropriate command-line switch is
// present, bailing out of the app we can't.
void EnableHeapProfiler(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(switches::kMemoryProfiling))
    if (!LoadMemoryProfiler())
      exit(-1);
#endif
}

void CommonSubprocessInit() {
  // Initialize ResourceBundle which handles files loaded from external
  // sources.  The language should have been passed in to us from the
  // browser process as a command line flag.
  ResourceBundle::InitSharedInstance(std::wstring());

#if defined(OS_WIN)
  // HACK: Let Windows know that we have started.  This is needed to suppress
  // the IDC_APPSTARTING cursor from being displayed for a prolonged period
  // while a subprocess is starting.
  PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
  MSG msg;
  PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
#endif
}

}  // namespace

#if defined(OS_WIN)
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
#endif

#if defined(OS_MACOSX)
  DebugUtil::DisableOSCrashDumps();
#endif
  RegisterInvalidParamHandler();

  // The exit manager is in charge of calling the dtors of singleton objects.
  base::AtExitManager exit_manager;

  // We need this pool for all the objects created before we get to the
  // event loop, but we don't want to leave them hanging around until the
  // app quits. Each "main" needs to flush this pool right before it goes into
  // its main event loop to get rid of the cruft.
  base::ScopedNSAutoreleasePool autorelease_pool;

  // Initialize the command line.
#if defined(OS_WIN)
  CommandLine::Init(0, NULL);
#else
  CommandLine::Init(argc, argv);
#endif
  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();

#if defined(OS_WIN)
   // Must do this before any other usage of command line!
  if (::IncorrectChromeHtmlArguments(parsed_command_line.command_line_string()))
    return 1;
#endif

  int browser_pid;
  std::wstring process_type =
    parsed_command_line.GetSwitchValue(switches::kProcessType);
  if (process_type.empty()) {
    browser_pid = base::GetCurrentProcId();
  } else {
    std::wstring channel_name =
      parsed_command_line.GetSwitchValue(switches::kProcessChannelID);

    browser_pid = StringToInt(WideToASCII(channel_name));
    DCHECK(browser_pid != 0);
  }
  SetupCRT(parsed_command_line);

  // Initialize the Chrome path provider.
  chrome::RegisterPathProvider();

  // Initialize the Stats Counters table.  With this initialized,
  // the StatsViewer can be utilized to read counters outside of
  // Chrome.  These lines can be commented out to effectively turn
  // counters 'off'.  The table is created and exists for the life
  // of the process.  It is not cleaned up.
  // TODO(port): we probably need to shut this down correctly to avoid
  // leaking shared memory regions on posix platforms.
  std::string statsfile =
      StringPrintf("%s-%d", chrome::kStatsFilename, browser_pid);
  StatsTable *stats_table = new StatsTable(statsfile,
      chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
  StatsTable::set_current(stats_table);

  StatsScope<StatsCounterTimer>
      startup_timer(chrome::Counters::chrome_main());

  // Enable the heap profiler as early as possible!
  EnableHeapProfiler(parsed_command_line);

  // Enable Message Loop related state asap.
  if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
    MessageLoop::EnableHistogrammer(true);

  // Checks if the sandbox is enabled in this process and initializes it if this
  // is the case. The crash handler depends on this so it has to be done before
  // its initialization.
  SandboxInitWrapper sandbox_wrapper;
#if defined(OS_WIN)
  sandbox_wrapper.SetServices(sandbox_info);
#endif
  sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);

#if defined(OS_WIN)
  _Module.Init(NULL, instance);
#endif

  // Notice a user data directory override if any
  const std::wstring user_data_dir =
      parsed_command_line.GetSwitchValue(switches::kUserDataDir);
  if (!user_data_dir.empty())
    PathService::Override(chrome::DIR_USER_DATA, user_data_dir);

  bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
    // This is an unsupported and not fully tested mode, so don't enable it for
    // official Chrome builds.
    false;
#else
    parsed_command_line.HasSwitch(switches::kSingleProcess);
#endif
  if (single_process)
    RenderProcessHost::set_run_renderer_in_process(true);
#if defined(OS_MACOSX)
  // TODO(port-mac): This is from renderer_main_platform_delegate.cc.
  // shess tried to refactor things appropriately, but it sprawled out
  // of control because different platforms needed different styles of
  // initialization.  Try again once we understand the process
  // architecture needed and where it should live.
  if (single_process)
    InitWebCoreSystemInterface();
#endif

  bool icu_result = icu_util::Initialize();
  CHECK(icu_result);

  logging::OldFileDeletionState file_state =
      logging::APPEND_TO_OLD_LOG_FILE;
  if (process_type.empty()) {
    file_state = logging::DELETE_OLD_LOG_FILE;
  }
  logging::InitChromeLogging(parsed_command_line, file_state);

#ifdef NDEBUG
  if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
      parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
#if defined(OS_WIN)
    logging::SetLogReportHandler(ChromeAssert);
#endif
  }
#endif  // NDEBUG

  if (!process_type.empty())
    CommonSubprocessInit();

  startup_timer.Stop();  // End of Startup Time Measurement.

  MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
                                 &autorelease_pool);

  // TODO(port): turn on these main() functions as they've been de-winified.
  int rv = -1;
  if (process_type == switches::kRendererProcess) {
    rv = RendererMain(main_params);
  } else if (process_type == switches::kPluginProcess) {
#if defined(OS_WIN)
    rv = PluginMain(main_params);
#endif
  } else if (process_type == switches::kWorkerProcess) {
#if defined(OS_WIN)
    rv = WorkerMain(main_params);
#endif
  } else if (process_type.empty()) {
#if defined(OS_LINUX)
    // gtk_init() can change |argc| and |argv|, but nobody else uses them.
    gtk_init(&argc, const_cast<char***>(&argv));
#endif

    ScopedOleInitializer ole_initializer;
    rv = BrowserMain(main_params);
  } else {
    NOTREACHED() << "Unknown process type";
  }

  if (!process_type.empty()) {
    ResourceBundle::CleanupSharedInstance();
  }

#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif  // _CRTDBG_MAP_ALLOC

  _Module.Term();
#endif

  logging::CleanupChromeLogging();

  return rv;
}
<commit_msg>Pipe fatal GTK messages through our logging system.<commit_after>// 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.

// TODO(port): the ifdefs in here are a first step towards trying to determine
// the correct abstraction for all the OS functionality required at this
// stage of process initialization. It should not be taken as a final
// abstraction.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <algorithm>
#include <atlbase.h>
#include <atlapp.h>
#include <malloc.h>
#include <new.h>
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug_util.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#if defined(OS_WIN)
#include "base/win_util.h"
#endif
#include "chrome/app/scoped_ole_initializer.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/sandbox_init_wrapper.h"
#if defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#include "tools/memory_watcher/memory_watcher.h"
#endif
#if defined(OS_MACOSX)
#include "third_party/WebKit/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
#endif

extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);

#if defined(OS_WIN)
// TODO(erikkay): isn't this already defined somewhere?
#define DLLEXPORT __declspec(dllexport)

// We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
extern "C" {
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line);
}
#elif defined(OS_POSIX)
extern "C" {
int ChromeMain(int argc, const char** argv);
}
#endif

namespace {

#if defined(OS_WIN)
const wchar_t kProfilingDll[] = L"memory_watcher.dll";

// Load the memory profiling DLL.  All it needs to be activated
// is to be loaded.  Return true on success, false otherwise.
bool LoadMemoryProfiler() {
  HMODULE prof_module = LoadLibrary(kProfilingDll);
  return prof_module != NULL;
}

CAppModule _Module;

#pragma optimize("", off)
// Handlers for invalid parameter and pure call. They generate a breakpoint to
// tell breakpad that it needs to dump the process.
void InvalidParameter(const wchar_t* expression, const wchar_t* function,
                      const wchar_t* file, unsigned int line,
                      uintptr_t reserved) {
  __debugbreak();
}

void PureCall() {
  __debugbreak();
}

int OnNoMemory(size_t memory_size) {
  __debugbreak();
  // Return memory_size so it is not optimized out. Make sure the return value
  // is at least 1 so malloc/new is retried, especially useful when under a
  // debugger.
  return memory_size ? static_cast<int>(memory_size) : 1;
}

// Handlers to silently dump the current process when there is an assert in
// chrome.
void ChromeAssert(const std::string& str) {
  // Get the breakpad pointer from chrome.exe
  typedef void (__stdcall *DumpProcessFunction)();
  DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
      ::GetProcAddress(::GetModuleHandle(L"chrome.exe"), "DumpProcess"));
  if (DumpProcess)
    DumpProcess();
}

#pragma optimize("", on)

// Early versions of Chrome incorrectly registered a chromehtml: URL handler.
// Later versions fixed the registration but in some cases (e.g. Vista and non-
// admin installs) the fix could not be applied.  This prevents Chrome to be
// launched with the incorrect format.
// CORRECT: <broser.exe> -- "chromehtml:<url>"
// INVALID: <broser.exe> "chromehtml:<url>"
bool IncorrectChromeHtmlArguments(const std::wstring& command_line) {
  const wchar_t kChromeHtml[] = L"-- \"chromehtml:";
  const wchar_t kOffset = 5;  // Where chromehtml: starts in above
  std::wstring command_line_lower = command_line;

  // We are only searching for ASCII characters so this is OK.
  StringToLowerASCII(&command_line_lower);

  std::wstring::size_type pos = command_line_lower.find(
      kChromeHtml + kOffset);

  if (pos == std::wstring::npos)
    return false;

  // The browser is being launched with chromehtml: somewhere on the command
  // line.  We will not launch unless it's preceded by the -- switch terminator.
  if (pos >= kOffset) {
    if (equal(kChromeHtml, kChromeHtml + arraysize(kChromeHtml) - 1,
        command_line_lower.begin() + pos - kOffset)) {
      return false;
    }
  }

  return true;
}

#endif  // OS_WIN

#if defined(OS_LINUX)
static void GtkFatalLogHandler(const gchar* log_domain,
                               GLogLevelFlags log_level,
                               const gchar* message,
                               gpointer userdata) {
  if (!log_domain)
    log_domain = "<all>";
  if (!message)
    message = "<no message>";

  NOTREACHED() << "GTK: (" << log_domain << "): " << message;
}
#endif

// Register the invalid param handler and pure call handler to be able to
// notify breakpad when it happens.
void RegisterInvalidParamHandler() {
#if defined(OS_WIN)
  _set_invalid_parameter_handler(InvalidParameter);
  _set_purecall_handler(PureCall);
  // Gather allocation failure.
  _set_new_handler(&OnNoMemory);
  // Make sure malloc() calls the new handler too.
  _set_new_mode(1);
#endif
}

void SetupCRT(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#else
  if (!parsed_command_line.HasSwitch(switches::kDisableBreakpad)) {
    _CrtSetReportMode(_CRT_ASSERT, 0);
  }
#endif

  // Enable the low fragmentation heap for the CRT heap. The heap is not changed
  // if the process is run under the debugger is enabled or if certain gflags
  // are set.
  bool use_lfh = false;
  if (parsed_command_line.HasSwitch(switches::kUseLowFragHeapCrt))
    use_lfh = parsed_command_line.GetSwitchValue(switches::kUseLowFragHeapCrt)
        != L"false";
  if (use_lfh) {
    void* crt_heap = reinterpret_cast<void*>(_get_heap_handle());
    ULONG enable_lfh = 2;
    HeapSetInformation(crt_heap, HeapCompatibilityInformation,
                       &enable_lfh, sizeof(enable_lfh));
  }
#endif
}

// Enable the heap profiler if the appropriate command-line switch is
// present, bailing out of the app we can't.
void EnableHeapProfiler(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(switches::kMemoryProfiling))
    if (!LoadMemoryProfiler())
      exit(-1);
#endif
}

void CommonSubprocessInit() {
  // Initialize ResourceBundle which handles files loaded from external
  // sources.  The language should have been passed in to us from the
  // browser process as a command line flag.
  ResourceBundle::InitSharedInstance(std::wstring());

#if defined(OS_WIN)
  // HACK: Let Windows know that we have started.  This is needed to suppress
  // the IDC_APPSTARTING cursor from being displayed for a prolonged period
  // while a subprocess is starting.
  PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
  MSG msg;
  PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
#endif
}

}  // namespace

#if defined(OS_WIN)
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
#endif

#if defined(OS_MACOSX)
  DebugUtil::DisableOSCrashDumps();
#endif
  RegisterInvalidParamHandler();

  // The exit manager is in charge of calling the dtors of singleton objects.
  base::AtExitManager exit_manager;

  // We need this pool for all the objects created before we get to the
  // event loop, but we don't want to leave them hanging around until the
  // app quits. Each "main" needs to flush this pool right before it goes into
  // its main event loop to get rid of the cruft.
  base::ScopedNSAutoreleasePool autorelease_pool;

  // Initialize the command line.
#if defined(OS_WIN)
  CommandLine::Init(0, NULL);
#else
  CommandLine::Init(argc, argv);
#endif
  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();

#if defined(OS_WIN)
   // Must do this before any other usage of command line!
  if (::IncorrectChromeHtmlArguments(parsed_command_line.command_line_string()))
    return 1;
#endif

  int browser_pid;
  std::wstring process_type =
    parsed_command_line.GetSwitchValue(switches::kProcessType);
  if (process_type.empty()) {
    browser_pid = base::GetCurrentProcId();
  } else {
    std::wstring channel_name =
      parsed_command_line.GetSwitchValue(switches::kProcessChannelID);

    browser_pid = StringToInt(WideToASCII(channel_name));
    DCHECK(browser_pid != 0);
  }
  SetupCRT(parsed_command_line);

  // Initialize the Chrome path provider.
  chrome::RegisterPathProvider();

  // Initialize the Stats Counters table.  With this initialized,
  // the StatsViewer can be utilized to read counters outside of
  // Chrome.  These lines can be commented out to effectively turn
  // counters 'off'.  The table is created and exists for the life
  // of the process.  It is not cleaned up.
  // TODO(port): we probably need to shut this down correctly to avoid
  // leaking shared memory regions on posix platforms.
  std::string statsfile =
      StringPrintf("%s-%d", chrome::kStatsFilename, browser_pid);
  StatsTable *stats_table = new StatsTable(statsfile,
      chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
  StatsTable::set_current(stats_table);

  StatsScope<StatsCounterTimer>
      startup_timer(chrome::Counters::chrome_main());

  // Enable the heap profiler as early as possible!
  EnableHeapProfiler(parsed_command_line);

  // Enable Message Loop related state asap.
  if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
    MessageLoop::EnableHistogrammer(true);

  // Checks if the sandbox is enabled in this process and initializes it if this
  // is the case. The crash handler depends on this so it has to be done before
  // its initialization.
  SandboxInitWrapper sandbox_wrapper;
#if defined(OS_WIN)
  sandbox_wrapper.SetServices(sandbox_info);
#endif
  sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);

#if defined(OS_WIN)
  _Module.Init(NULL, instance);
#endif

  // Notice a user data directory override if any
  const std::wstring user_data_dir =
      parsed_command_line.GetSwitchValue(switches::kUserDataDir);
  if (!user_data_dir.empty())
    PathService::Override(chrome::DIR_USER_DATA, user_data_dir);

  bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
    // This is an unsupported and not fully tested mode, so don't enable it for
    // official Chrome builds.
    false;
#else
    parsed_command_line.HasSwitch(switches::kSingleProcess);
#endif
  if (single_process)
    RenderProcessHost::set_run_renderer_in_process(true);
#if defined(OS_MACOSX)
  // TODO(port-mac): This is from renderer_main_platform_delegate.cc.
  // shess tried to refactor things appropriately, but it sprawled out
  // of control because different platforms needed different styles of
  // initialization.  Try again once we understand the process
  // architecture needed and where it should live.
  if (single_process)
    InitWebCoreSystemInterface();
#endif

  bool icu_result = icu_util::Initialize();
  CHECK(icu_result);

  logging::OldFileDeletionState file_state =
      logging::APPEND_TO_OLD_LOG_FILE;
  if (process_type.empty()) {
    file_state = logging::DELETE_OLD_LOG_FILE;
  }
  logging::InitChromeLogging(parsed_command_line, file_state);

#ifdef NDEBUG
  if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
      parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
#if defined(OS_WIN)
    logging::SetLogReportHandler(ChromeAssert);
#endif
  }
#endif  // NDEBUG

  if (!process_type.empty())
    CommonSubprocessInit();

  startup_timer.Stop();  // End of Startup Time Measurement.

  MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
                                 &autorelease_pool);

  // TODO(port): turn on these main() functions as they've been de-winified.
  int rv = -1;
  if (process_type == switches::kRendererProcess) {
    rv = RendererMain(main_params);
  } else if (process_type == switches::kPluginProcess) {
#if defined(OS_WIN)
    rv = PluginMain(main_params);
#endif
  } else if (process_type == switches::kWorkerProcess) {
#if defined(OS_WIN)
    rv = WorkerMain(main_params);
#endif
  } else if (process_type.empty()) {
#if defined(OS_LINUX)
    // gtk_init() can change |argc| and |argv|, but nobody else uses them.
    gtk_init(&argc, const_cast<char***>(&argv));
    // Register GTK assertions to go through our logging system.
    g_log_set_handler(NULL,  // All logging domains.
                      static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION |
                                                  G_LOG_FLAG_FATAL |
                                                  G_LOG_LEVEL_ERROR |
                                                  G_LOG_LEVEL_CRITICAL |
                                                  G_LOG_LEVEL_WARNING),
                      GtkFatalLogHandler,
                      NULL);
#endif

    ScopedOleInitializer ole_initializer;
    rv = BrowserMain(main_params);
  } else {
    NOTREACHED() << "Unknown process type";
  }

  if (!process_type.empty()) {
    ResourceBundle::CleanupSharedInstance();
  }

#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif  // _CRTDBG_MAP_ALLOC

  _Module.Term();
#endif

  logging::CleanupChromeLogging();

  return rv;
}
<|endoftext|>


<commit_before>// 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 "chrome/test/nacl/nacl_test.h"

#include "base/file_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

namespace {

const int kNaClTestTimeout = 20000;
const char kTestCompleteCookie[] = "status";
const char kTestCompleteSuccess[] = "OK";

const FilePath::CharType kBaseUrl[] =
    FILE_PATH_LITERAL("http://localhost:5103/");

const FilePath::CharType kSrpcHwHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_hw.html");
const FilePath::CharType kSrpcHwNexeFileName[] =
    FILE_PATH_LITERAL("srpc_hw.nexe");

const FilePath::CharType kSrpcBasicHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_basic.html");
const FilePath::CharType kSrpcBasicNexeFileName[] =
    FILE_PATH_LITERAL("srpc_test.nexe");

const FilePath::CharType kSrpcSockAddrHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_sockaddr.html");

const FilePath::CharType kSrpcShmHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_shm.html");
const FilePath::CharType kSrpcShmNexeFileName[] =
    FILE_PATH_LITERAL("srpc_shm.nexe");

const FilePath::CharType kSrpcPluginHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_plugin.html");

const FilePath::CharType kSrpcNrdXferHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_xfer.html");
const FilePath::CharType kSrpcNrdClientNexeFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_client.nexe");
const FilePath::CharType kSrpcNrdServerNexeFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_server.nexe");

const FilePath::CharType kServerHtmlFileName[] =
    FILE_PATH_LITERAL("server_test.html");

}  // anonymous namespace

NaClTest::NaClTest()
    : UITest() {
  launch_arguments_.AppendSwitch(switches::kEnableNaCl);
#if defined(OS_MACOSX)
  launch_arguments_.AppendSwitch(switches::kNoSandbox);
#endif
}

NaClTest::~NaClTest() {}

FilePath NaClTest::GetTestRootDir() {
  FilePath path;
  PathService::Get(base::DIR_SOURCE_ROOT, &path);
  path = path.AppendASCII("native_client");
  path = path.AppendASCII("tests");
  return path;
}

FilePath NaClTest::GetTestBinariesDir() {
  FilePath path = GetTestRootDir();
  path = path.AppendASCII("prebuilt");
  bool use_x64_nexes = false;
#if defined(OS_WIN)
  if (NaClOsIs64BitWindows())
    use_x64_nexes = true;
#endif

  if (use_x64_nexes)
    path = path.AppendASCII("x64");
  else
    path = path.AppendASCII("x86");
  return path;
}

// static
GURL NaClTest::GetTestUrl(const FilePath& filename) {
  FilePath path(kBaseUrl);
  path = path.Append(filename);
  return GURL(path.value());
}

void NaClTest::WaitForFinish(const FilePath& filename,
                             int wait_time) {
  GURL url = GetTestUrl(filename);
  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  bool test_result = WaitUntilCookieValue(tab.get(),
                                          url,
                                          kTestCompleteCookie,
                                          action_timeout_ms(),
                                          wait_time,
                                          kTestCompleteSuccess);
  EXPECT_TRUE(test_result);
}

void NaClTest::RunTest(const FilePath& filename, int timeout) {
  GURL url = GetTestUrl(filename);
  NavigateToURL(url);
  WaitForFinish(filename, timeout);
}

void NaClTest::PrepareSrpcHwTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc_hw");
  FilePath html_file = test_dir.Append(kSrpcHwHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcHwNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcHwHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcHwNexeFileName)));
}

void NaClTest::PrepareServerTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("server");
  FilePath html_file = test_dir.Append(kServerHtmlFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kServerHtmlFileName)));
}

void NaClTest::PrepareSrpcBasicTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcBasicHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcBasicNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcBasicHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcBasicNexeFileName)));
}

void NaClTest::PrepareSrpcSockAddrTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcSockAddrHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcNrdServerNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcSockAddrHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcNrdServerNexeFileName)));
}

void NaClTest::PrepareSrpcShmTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcShmHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcShmNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcShmHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcShmNexeFileName)));
}

void NaClTest::PrepareSrpcPluginTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcPluginHtmlFileName);
  FilePath nexe_file1 = GetTestBinariesDir().Append(kSrpcNrdClientNexeFileName);
  FilePath nexe_file2 = GetTestBinariesDir().Append(kSrpcBasicNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file1));
  ASSERT_TRUE(file_util::PathExists(nexe_file2));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcPluginHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file1,
      test_root_dir.Append(kSrpcNrdClientNexeFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file2,
      test_root_dir.Append(kSrpcBasicNexeFileName)));
}

void NaClTest::PrepareSrpcNrdXferTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcNrdXferHtmlFileName);
  FilePath nexe_file1 = GetTestBinariesDir().Append(kSrpcNrdClientNexeFileName);
  FilePath nexe_file2 = GetTestBinariesDir().Append(kSrpcNrdServerNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file1));
  ASSERT_TRUE(file_util::PathExists(nexe_file2));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcNrdXferHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file1,
      test_root_dir.Append(kSrpcNrdClientNexeFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file2,
      test_root_dir.Append(kSrpcNrdServerNexeFileName)));
}

void NaClTest::SetUp() {
  FilePath nacl_test_dir = GetTestRootDir();
  PrepareSrpcHwTest(nacl_test_dir);
  PrepareServerTest(nacl_test_dir);
  PrepareSrpcBasicTest(nacl_test_dir);
  PrepareSrpcSockAddrTest(nacl_test_dir);
  PrepareSrpcShmTest(nacl_test_dir);
  PrepareSrpcPluginTest(nacl_test_dir);
  PrepareSrpcNrdXferTest(nacl_test_dir);

  UITest::SetUp();

  StartHttpServerWithPort(nacl_test_dir, L"5103");
}

void NaClTest::TearDown() {
  StopHttpServer();
  UITest::TearDown();
}

int NaClTest::NaClTestTimeout() {
  return std::max(kNaClTestTimeout, action_max_timeout_ms());
}

TEST_F(NaClTest, ServerTest) {
  FilePath test_file(kServerHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcHelloWorld) {
  FilePath test_file(kSrpcHwHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcBasicTest) {
  FilePath test_file(kSrpcBasicHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcSockAddrTest) {
  FilePath test_file(kSrpcSockAddrHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcShmTest) {
  FilePath test_file(kSrpcShmHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcPluginTest) {
  FilePath test_file(kSrpcPluginHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcNrdXferTest) {
  FilePath test_file(kSrpcNrdXferHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}
<commit_msg>Make the tests use 64-bit nexes when running 64-bit Linux Chrome<commit_after>// 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 "chrome/test/nacl/nacl_test.h"

#include "base/file_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

namespace {

const int kNaClTestTimeout = 20000;
const char kTestCompleteCookie[] = "status";
const char kTestCompleteSuccess[] = "OK";

const FilePath::CharType kBaseUrl[] =
    FILE_PATH_LITERAL("http://localhost:5103/");

const FilePath::CharType kSrpcHwHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_hw.html");
const FilePath::CharType kSrpcHwNexeFileName[] =
    FILE_PATH_LITERAL("srpc_hw.nexe");

const FilePath::CharType kSrpcBasicHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_basic.html");
const FilePath::CharType kSrpcBasicNexeFileName[] =
    FILE_PATH_LITERAL("srpc_test.nexe");

const FilePath::CharType kSrpcSockAddrHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_sockaddr.html");

const FilePath::CharType kSrpcShmHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_shm.html");
const FilePath::CharType kSrpcShmNexeFileName[] =
    FILE_PATH_LITERAL("srpc_shm.nexe");

const FilePath::CharType kSrpcPluginHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_plugin.html");

const FilePath::CharType kSrpcNrdXferHtmlFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_xfer.html");
const FilePath::CharType kSrpcNrdClientNexeFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_client.nexe");
const FilePath::CharType kSrpcNrdServerNexeFileName[] =
    FILE_PATH_LITERAL("srpc_nrd_server.nexe");

const FilePath::CharType kServerHtmlFileName[] =
    FILE_PATH_LITERAL("server_test.html");

}  // anonymous namespace

NaClTest::NaClTest()
    : UITest() {
  launch_arguments_.AppendSwitch(switches::kEnableNaCl);
#if defined(OS_MACOSX)
  launch_arguments_.AppendSwitch(switches::kNoSandbox);
#endif
}

NaClTest::~NaClTest() {}

FilePath NaClTest::GetTestRootDir() {
  FilePath path;
  PathService::Get(base::DIR_SOURCE_ROOT, &path);
  path = path.AppendASCII("native_client");
  path = path.AppendASCII("tests");
  return path;
}

FilePath NaClTest::GetTestBinariesDir() {
  FilePath path = GetTestRootDir();
  path = path.AppendASCII("prebuilt");
  bool use_x64_nexes = false;
#if defined(OS_WIN)
  if (NaClOsIs64BitWindows())
    use_x64_nexes = true;
#elif defined(OS_LINUX) && defined(__LP64__)
  use_x64_nexes = true;
#endif

  if (use_x64_nexes)
    path = path.AppendASCII("x64");
  else
    path = path.AppendASCII("x86");
  return path;
}

// static
GURL NaClTest::GetTestUrl(const FilePath& filename) {
  FilePath path(kBaseUrl);
  path = path.Append(filename);
  return GURL(path.value());
}

void NaClTest::WaitForFinish(const FilePath& filename,
                             int wait_time) {
  GURL url = GetTestUrl(filename);
  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  bool test_result = WaitUntilCookieValue(tab.get(),
                                          url,
                                          kTestCompleteCookie,
                                          action_timeout_ms(),
                                          wait_time,
                                          kTestCompleteSuccess);
  EXPECT_TRUE(test_result);
}

void NaClTest::RunTest(const FilePath& filename, int timeout) {
  GURL url = GetTestUrl(filename);
  NavigateToURL(url);
  WaitForFinish(filename, timeout);
}

void NaClTest::PrepareSrpcHwTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc_hw");
  FilePath html_file = test_dir.Append(kSrpcHwHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcHwNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcHwHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcHwNexeFileName)));
}

void NaClTest::PrepareServerTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("server");
  FilePath html_file = test_dir.Append(kServerHtmlFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kServerHtmlFileName)));
}

void NaClTest::PrepareSrpcBasicTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcBasicHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcBasicNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcBasicHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcBasicNexeFileName)));
}

void NaClTest::PrepareSrpcSockAddrTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcSockAddrHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcNrdServerNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcSockAddrHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcNrdServerNexeFileName)));
}

void NaClTest::PrepareSrpcShmTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcShmHtmlFileName);
  FilePath nexe_file = GetTestBinariesDir().Append(kSrpcShmNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcShmHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file,
      test_root_dir.Append(kSrpcShmNexeFileName)));
}

void NaClTest::PrepareSrpcPluginTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcPluginHtmlFileName);
  FilePath nexe_file1 = GetTestBinariesDir().Append(kSrpcNrdClientNexeFileName);
  FilePath nexe_file2 = GetTestBinariesDir().Append(kSrpcBasicNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file1));
  ASSERT_TRUE(file_util::PathExists(nexe_file2));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcPluginHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file1,
      test_root_dir.Append(kSrpcNrdClientNexeFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file2,
      test_root_dir.Append(kSrpcBasicNexeFileName)));
}

void NaClTest::PrepareSrpcNrdXferTest(FilePath test_root_dir) {
  FilePath test_dir = test_root_dir.AppendASCII("srpc");
  FilePath html_file = test_dir.Append(kSrpcNrdXferHtmlFileName);
  FilePath nexe_file1 = GetTestBinariesDir().Append(kSrpcNrdClientNexeFileName);
  FilePath nexe_file2 = GetTestBinariesDir().Append(kSrpcNrdServerNexeFileName);
  ASSERT_TRUE(file_util::PathExists(html_file));
  ASSERT_TRUE(file_util::PathExists(nexe_file1));
  ASSERT_TRUE(file_util::PathExists(nexe_file2));
  // Now copy the files into the test directory
  ASSERT_TRUE(file_util::CopyFile(
      html_file,
      test_root_dir.Append(kSrpcNrdXferHtmlFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file1,
      test_root_dir.Append(kSrpcNrdClientNexeFileName)));
  ASSERT_TRUE(file_util::CopyFile(
      nexe_file2,
      test_root_dir.Append(kSrpcNrdServerNexeFileName)));
}

void NaClTest::SetUp() {
  FilePath nacl_test_dir = GetTestRootDir();
  PrepareSrpcHwTest(nacl_test_dir);
  PrepareServerTest(nacl_test_dir);
  PrepareSrpcBasicTest(nacl_test_dir);
  PrepareSrpcSockAddrTest(nacl_test_dir);
  PrepareSrpcShmTest(nacl_test_dir);
  PrepareSrpcPluginTest(nacl_test_dir);
  PrepareSrpcNrdXferTest(nacl_test_dir);

  UITest::SetUp();

  StartHttpServerWithPort(nacl_test_dir, L"5103");
}

void NaClTest::TearDown() {
  StopHttpServer();
  UITest::TearDown();
}

int NaClTest::NaClTestTimeout() {
  return std::max(kNaClTestTimeout, action_max_timeout_ms());
}

TEST_F(NaClTest, ServerTest) {
  FilePath test_file(kServerHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcHelloWorld) {
  FilePath test_file(kSrpcHwHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcBasicTest) {
  FilePath test_file(kSrpcBasicHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcSockAddrTest) {
  FilePath test_file(kSrpcSockAddrHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcShmTest) {
  FilePath test_file(kSrpcShmHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcPluginTest) {
  FilePath test_file(kSrpcPluginHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}

TEST_F(NaClTest, SrpcNrdXferTest) {
  FilePath test_file(kSrpcNrdXferHtmlFileName);
  RunTest(test_file, NaClTestTimeout());
}
<|endoftext|>