<commit_before>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_WS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<commit_msg>clear history when using clear button in RPC console<commit_after>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_HISTORY = 50;
const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_WS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    history.clear();
    historyPtr = 0;
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<|endoftext|>


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

#include "chrome/browser/printing/print_preview_tab_controller.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "googleurl/src/gurl.h"

namespace {

typedef InProcessBrowserTest PrintPreviewTabControllerBrowserTest;

// Test to verify that when a preview tab navigates, we can create a new print
// preview tab for both initiator tab and new preview tab contents.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       NavigateFromPrintPreviewTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  GURL url(chrome::kAboutBlankURL);
  ui_test_utils::NavigateToURL(browser(), url);
  EXPECT_EQ(url, preview_tab->tab_contents()->GetURL());

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New preview tab is created.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_NE(new_preview_tab, preview_tab);

  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Newest preview tab is created and the previously created preview tab is not
  // merely activated.
  EXPECT_EQ(4, browser()->tab_count());
  EXPECT_NE(newest_preview_tab, new_preview_tab);
}

// Test to verify that when a initiator tab navigates, we can create a new
// preview tab for the new tab contents. But we cannot create a preview tab for
// the old preview tab.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       NavigateFromInitiatorTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  // Activate initiator tab.
  browser()->ActivateTabAt(0, true);
  GURL url(chrome::kChromeUINewTabURL);
  ui_test_utils::NavigateToURL(browser(), url);

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New preview tab is created.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_NE(new_preview_tab, preview_tab);

  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Make sure preview tab is not created for |preview_tab|.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_EQ(newest_preview_tab, preview_tab);
}

// Test to verify that even after reloading initiator tab and preview tab,
// their association exists.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       ReloadInitiatorTabAndPreviewTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  // Activate initiator tab and reload.
  browser()->ActivateTabAt(0, true);
  browser()->Reload(CURRENT_TAB);

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // Old preview tab is activated.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(new_preview_tab, preview_tab);

  // Reload preview tab.
  browser()->Reload(CURRENT_TAB);
  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Make sure new preview tab is not created for |preview_tab|.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(newest_preview_tab, preview_tab);
}

// Test that print preview tabs are placed correctly.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       OpenPreviewTabInCorrectPosition) {
  const int kTabCount = 4;
  // Create kTabCount - 1 tabs since we start with 1 tab already.
  for (int i = 0; i < kTabCount - 1; ++i) {
    browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
    p.disposition = NEW_FOREGROUND_TAB;
    browser::Navigate(&p);
  }
  EXPECT_EQ(kTabCount, browser()->tab_count());

  // Create a print preview tab.
  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  const int kInitiatorTabIndex = 1;
  TabContentsWrapper* initiator_tab =
      browser()->GetTabContentsWrapperAt(kInitiatorTabIndex);
  ASSERT_TRUE(initiator_tab);
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);
  EXPECT_TRUE(preview_tab);

  // Check the preview tab's location.
  EXPECT_EQ(preview_tab,
            browser()->GetTabContentsWrapperAt(kInitiatorTabIndex + 1));
  EXPECT_EQ(preview_tab, browser()->GetSelectedTabContentsWrapper());
}

// Test that print preview tabs created by pop-up windows are placed correctly.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       OpenPreviewTabFromPopupInCorrectPosition) {
  const int kTabCount = 4;
  // Create kTabCount - 1 tabs since we start with 1 tab already.
  for (int i = 0; i < kTabCount - 1; ++i) {
    browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
    p.disposition = NEW_FOREGROUND_TAB;
    browser::Navigate(&p);
  }
  EXPECT_EQ(kTabCount, browser()->tab_count());

  // Create a popup
  browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
  p.disposition = NEW_POPUP;
  ui_test_utils::NavigateToURL(&p);

#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
  // Navigate() should have opened a new tab on CrOS.
  EXPECT_EQ(browser(), p.browser);
  EXPECT_EQ(Browser::TYPE_TABBED, p.browser->type());
#else
  // Navigate() should have opened a new popup window.
  EXPECT_NE(browser(), p.browser);
  EXPECT_EQ(Browser::TYPE_POPUP, p.browser->type());
#endif
  ASSERT_TRUE(p.target_contents);

  // Create a print preview tab.
  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(p.target_contents);
  EXPECT_TRUE(preview_tab);

  int tab_position = kTabCount;
#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
  // Increment position since CrOS opened a new tab instead of a popup.
  tab_position++;
#endif

  // Check the preview tab's location.
  EXPECT_EQ(preview_tab, browser()->GetTabContentsWrapperAt(tab_position));
  EXPECT_EQ(preview_tab, browser()->GetSelectedTabContentsWrapper());
}

}  // namespace
<commit_msg>Fix OpenPreviewTabFromPopupInCorrectPosition test on Linux Views.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/print_preview_tab_controller.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "googleurl/src/gurl.h"

namespace {

typedef InProcessBrowserTest PrintPreviewTabControllerBrowserTest;

// Test to verify that when a preview tab navigates, we can create a new print
// preview tab for both initiator tab and new preview tab contents.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       NavigateFromPrintPreviewTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  GURL url(chrome::kAboutBlankURL);
  ui_test_utils::NavigateToURL(browser(), url);
  EXPECT_EQ(url, preview_tab->tab_contents()->GetURL());

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New preview tab is created.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_NE(new_preview_tab, preview_tab);

  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Newest preview tab is created and the previously created preview tab is not
  // merely activated.
  EXPECT_EQ(4, browser()->tab_count());
  EXPECT_NE(newest_preview_tab, new_preview_tab);
}

// Test to verify that when a initiator tab navigates, we can create a new
// preview tab for the new tab contents. But we cannot create a preview tab for
// the old preview tab.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       NavigateFromInitiatorTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  // Activate initiator tab.
  browser()->ActivateTabAt(0, true);
  GURL url(chrome::kChromeUINewTabURL);
  ui_test_utils::NavigateToURL(browser(), url);

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New preview tab is created.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_NE(new_preview_tab, preview_tab);

  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Make sure preview tab is not created for |preview_tab|.
  EXPECT_EQ(3, browser()->tab_count());
  EXPECT_EQ(newest_preview_tab, preview_tab);
}

// Test to verify that even after reloading initiator tab and preview tab,
// their association exists.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       ReloadInitiatorTabAndPreviewTab) {
  ASSERT_TRUE(browser());
  BrowserList::SetLastActive(browser());
  ASSERT_TRUE(BrowserList::GetLastActive());

  // Lets start with one window with one tab.
  EXPECT_EQ(1u, BrowserList::size());
  EXPECT_EQ(1, browser()->tab_count());

  // Create a reference to initiator tab contents.
  TabContentsWrapper* initiator_tab =
      browser()->GetSelectedTabContentsWrapper();
  ASSERT_TRUE(initiator_tab);

  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  // Get the preview tab for initiator tab.
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // New print preview tab is created. Current focus is on preview tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_NE(initiator_tab, preview_tab);

  // Activate initiator tab and reload.
  browser()->ActivateTabAt(0, true);
  browser()->Reload(CURRENT_TAB);

  // Get the print preview tab for initiator tab.
  TabContentsWrapper* new_preview_tab =
     tab_controller->GetOrCreatePreviewTab(initiator_tab);

  // Old preview tab is activated.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(new_preview_tab, preview_tab);

  // Reload preview tab.
  browser()->Reload(CURRENT_TAB);
  // Get the print preview tab for old preview tab.
  TabContentsWrapper* newest_preview_tab =
  tab_controller->GetOrCreatePreviewTab(preview_tab);

  // Make sure new preview tab is not created for |preview_tab|.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(newest_preview_tab, preview_tab);
}

// Test that print preview tabs are placed correctly.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       OpenPreviewTabInCorrectPosition) {
  const int kTabCount = 4;
  // Create kTabCount - 1 tabs since we start with 1 tab already.
  for (int i = 0; i < kTabCount - 1; ++i) {
    browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
    p.disposition = NEW_FOREGROUND_TAB;
    browser::Navigate(&p);
  }
  EXPECT_EQ(kTabCount, browser()->tab_count());

  // Create a print preview tab.
  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  const int kInitiatorTabIndex = 1;
  TabContentsWrapper* initiator_tab =
      browser()->GetTabContentsWrapperAt(kInitiatorTabIndex);
  ASSERT_TRUE(initiator_tab);
  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(initiator_tab);
  EXPECT_TRUE(preview_tab);

  // Check the preview tab's location.
  EXPECT_EQ(preview_tab,
            browser()->GetTabContentsWrapperAt(kInitiatorTabIndex + 1));
  EXPECT_EQ(preview_tab, browser()->GetSelectedTabContentsWrapper());
}

// Test that print preview tabs created by pop-up windows are placed correctly.
IN_PROC_BROWSER_TEST_F(PrintPreviewTabControllerBrowserTest,
                       OpenPreviewTabFromPopupInCorrectPosition) {
  const int kTabCount = 4;
  // Create kTabCount - 1 tabs since we start with 1 tab already.
  for (int i = 0; i < kTabCount - 1; ++i) {
    browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
    p.disposition = NEW_FOREGROUND_TAB;
    browser::Navigate(&p);
  }
  EXPECT_EQ(kTabCount, browser()->tab_count());

  // Create a popup
  browser::NavigateParams p(browser(), GURL(), PageTransition::LINK);
  p.disposition = NEW_POPUP;
  ui_test_utils::NavigateToURL(&p);

#if defined(OS_CHROMEOS)
  // Navigate() should have opened a new tab on CrOS.
  EXPECT_EQ(browser(), p.browser);
  EXPECT_EQ(Browser::TYPE_TABBED, p.browser->type());
#else
  // Navigate() should have opened a new popup window.
  EXPECT_NE(browser(), p.browser);
  EXPECT_EQ(Browser::TYPE_POPUP, p.browser->type());
#endif
  ASSERT_TRUE(p.target_contents);

  // Create a print preview tab.
  scoped_refptr<printing::PrintPreviewTabController>
     tab_controller(new printing::PrintPreviewTabController());
  ASSERT_TRUE(tab_controller);

  TabContentsWrapper* preview_tab =
    tab_controller->GetOrCreatePreviewTab(p.target_contents);
  EXPECT_TRUE(preview_tab);

  int tab_position = kTabCount;
#if defined(OS_CHROMEOS)
  // Increment position since CrOS opened a new tab instead of a popup.
  tab_position++;
#endif

  // Check the preview tab's location.
  EXPECT_EQ(preview_tab, browser()->GetTabContentsWrapperAt(tab_position));
  EXPECT_EQ(preview_tab, browser()->GetSelectedTabContentsWrapper());
}

}  // namespace
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time waveforms!
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015, Music256a taught by Ge Wang (righteous!)
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* ----------------------#defines-------------------- */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

// amplitude definitions
#define MAX_AMP 1.0
#define MIN_AMP -1.0
#define BASELINE 0

/* ----------------------globals--------------------- */

// frequency
SAMPLE g_freq = 440;

// sample number
SAMPLE g_t = 0;

// wave width (default square wave)
SAMPLE g_width = 0.5;

// type of signal requested by user, enumerated in function determine_signal
int g_sig = 0;

/*---------------------------------------------------- */

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
          and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
          when opening the stream (default = NULL).
 * @return Zero to maintain normal stream. One to stop the stream and drain the
           output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data ) {

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         for(int i = 0; i < numFrames; i++)
         {
            /* Creates different waveforms based on user input by first generating a signal in the
             * even-indexed slots of the buffer. */
            switch(g_sig) {

                // sine
                case 1:
                    buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);
                    break;

                // saw
                case 2:
                    break;

                // pulse
                case 3:

                    /* (Sample % period) <= the width, or delay time, of the wave.
                     * Produces rectangular wave above the baseline. */
                    if (((int) g_t) % ((int) (MY_SRATE / g_freq)) <= (g_width * 10)) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    }

                    /* (Sample % period) >= the width, or delay time, of the wave.
                     * Produces rectangular wave below the baseline. */
                    else if (((int) g_t) % ((int) (MY_SRATE / g_freq)) >= (g_width * 10)) {
                        buffer[i * MY_CHANNELS] = MIN_AMP;
                    }
                    break;

                // noise (white noise to be more specific)
                case 4:
                    buffer[i * MY_CHANNELS] = (rand() % 100) / 10;
                    break;

                // impulse train
                case 5:

                    // signal sample shoots an impulse at the given frequency's fundamental period
                    if (((int) g_t) % ((int) (MY_SRATE / g_freq)) == 0) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    } else {
                        buffer[i * MY_CHANNELS] = BASELINE;
                    }
                    break;

                // if none of the above, stop the stream immediately.
                default:
                    return 2;
            }

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

/*
 * @funtion determine_signal Returns an integer based on the type of command given.
            Allows me to easily use a switch statement in the audio callback function
            for the different waveforms.
 * @param argc Number of command line arguments.
 * @param argv Array of strings containing command line arguments.
 */
int determine_signal(int argc, const char *argv[]) {
    string arg = string(argv[1]);
    char *endptr = 0;

    // checks third argument: frequency
    if (argc > 2) {
        g_freq = strtod(argv[2], &endptr);
        if (*endptr != '\0' || endptr == argv[2]) {
            cout << "The frequency you entered is not a double. Using default frequency 440 Hz." << endl;
            g_freq = 440;
        }

        // if no width given, use default width
        if (argc == 3) cout << "No width given. Using 0.5 as default width." << endl;
    }

    // checks fourth argument: width
    if (argc > 3) {
        g_width = strtod(argv[3], &endptr);
        if (*endptr != '\0' || endptr == argv[3]) {
            cout << "The width you entered is not a double. Using default width 1." << endl;
            g_width = 1;
        } else if (g_width == 1.0 || g_width == 0) {
            cout << "Must enter a width in the range (0, 1)." << endl;
            exit(1);
        }
    }

    // sine
    if (arg == "--sine") {
        return 1;
    }

    // saw
    else if (arg == "--saw"){
        return 2;
    }

    // pulse
    else if (arg == "--pulse"){
        return 3;
    }

    // noise
    else if (arg == "--noise"){
        return 4;
    }

    //impulse
    else if (arg == "--impulse") {
        return 5;
    }

    // arg is some other input not defined by this program
    else {
        return -1;
    }
}

int main(int argc, char const *argv[]) {

    // error: ./sig_gen with no additional arguments
    if (argc <= 1) {
        cout << "Not enough arguments. Must give type of signal generation." << endl;
        cout << "Input should be of form ./sig_gen [type] [frequency] [width]...";
        cout << "frequency and width are optional." << endl;
        exit(1);
    }

    // error: more than four arguments
    if (argc > 4) {
        cout << "Ignoring extraneous arguments..." << endl;
    }

    // determines which type of signal user wants to generate
    g_sig = determine_signal(argc, argv);

    // error: invalid waveform type
    if (g_sig < 0) {
        cout << "Must provide a valid type of waveform. --sine, --saw, --noise, --pulse, --impulse." << endl;
        exit(1);
    }

    // instantiate RtAudio object
    RtAudio audio;

    // frame size
    unsigned int bufferFrames = 512;
    unsigned int bufferBytes = 0;

    // check for audio devices
    if(audio.getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    audio.showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio.getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio.getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio.openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio.getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio.startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio.stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio.isStreamOpen())
            audio.closeStream();

    return 0;
}
<commit_msg>about to embark on the saw wave<commit_after>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time waveforms!
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015, Music256a taught by Ge Wang (righteous!)
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* ----------------------#defines-------------------- */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

// amplitude definitions
#define MAX_AMP 1.0
#define MIN_AMP -1.0
#define BASELINE 0

/* ----------------------globals--------------------- */

// frequency
SAMPLE g_freq = 440;

// sample number
SAMPLE g_t = 0;

// wave width (default square wave)
SAMPLE g_width = 0.5;

// type of signal requested by user, enumerated in function determine_signal
int g_sig = 0;

/*---------------------------------------------------- */

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
          and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
          when opening the stream (default = NULL).
 * @return Zero to maintain normal stream. One to stop the stream and drain the
           output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data ) {

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         for(int i = 0; i < numFrames; i++)
         {
            /* Creates different waveforms based on user input by first generating a signal in the
             * even-indexed slots of the buffer. */
            switch(g_sig) {

                // sine
                case 1:
                    buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);
                    break;

                // saw
                case 2:

                    /* (Sample % period) <= the width, or delay time, of the wave.
                     * Produces saw wave above the baseline. */
                    if (((int) g_t) % ((int) (MY_SRATE / g_freq)) <= g_width) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    }

                    /* (Sample % period) >= the width, or delay time, of the wave.
                     * Produces saw wave below the baseline. */
                    else if (((int) g_t) % ((int) (MY_SRATE / g_freq)) >= g_width) {
                        buffer[i * MY_CHANNELS] = MIN_AMP;
                    }
                    break;

                // pulse
                case 3:

                    /* (Sample % period) <= the width, or delay time, of the wave.
                     * Produces rectangular wave above the baseline. */
                    if (((int) g_t) % ((int) (MY_SRATE / g_freq)) <= g_width) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    }

                    /* (Sample % period) >= the width, or delay time, of the wave.
                     * Produces rectangular wave below the baseline. */
                    else if (((int) g_t) % ((int) (MY_SRATE / g_freq)) >= g_width) {
                        buffer[i * MY_CHANNELS] = MIN_AMP;
                    }
                    break;

                // noise (white noise to be more specific)
                case 4:
                    buffer[i * MY_CHANNELS] = (rand() % 100) / 10;
                    break;

                // impulse train
                case 5:

                    // signal sample shoots an impulse at the given frequency's fundamental period
                    if (((int) g_t) % ((int) (MY_SRATE / g_freq)) == 0) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    } else {
                        buffer[i * MY_CHANNELS] = BASELINE;
                    }
                    break;

                // if none of the above, stop the stream immediately.
                default:
                    return 2;
            }

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

/*
 * @funtion determine_signal Returns an integer based on the type of command given.
            Allows me to easily use a switch statement in the audio callback function
            for the different waveforms.
 * @param argc Number of command line arguments.
 * @param argv Array of strings containing command line arguments.
 */
int determine_signal(int argc, const char *argv[]) {
    string arg = string(argv[1]);
    char *endptr = 0;

    // checks third argument: frequency
    if (argc > 2) {
        g_freq = strtod(argv[2], &endptr);
        if (*endptr != '\0' || endptr == argv[2]) {
            cout << "The frequency you entered is not a double. Using default frequency 440 Hz." << endl;
            g_freq = 440;
        }

        // if no width given, use default width
        if (argc == 3) cout << "No width given. Using 0.5 as default width." << endl;
    }

    // checks fourth argument: width
    if (argc > 3) {
        g_width = strtod(argv[3], &endptr);
        if (*endptr != '\0' || endptr == argv[3]) {
            cout << "The width you entered is not a double. Using default width 1." << endl;
            g_width = 1;
        } else if (g_width >= 1.0 || g_width <= 0) {
            cout << "Must enter a width in the range (0, 1)." << endl;
            exit(1);
        }
    }

    // sine
    if (arg == "--sine") {
        return 1;
    }

    // saw
    else if (arg == "--saw"){
        return 2;
    }

    // pulse
    else if (arg == "--pulse"){
        return 3;
    }

    // noise
    else if (arg == "--noise"){
        return 4;
    }

    //impulse
    else if (arg == "--impulse") {
        return 5;
    }

    // arg is some other input not defined by this program
    else {
        return -1;
    }
}

int main(int argc, char const *argv[]) {

    // error: ./sig_gen with no additional arguments
    if (argc <= 1) {
        cout << "Not enough arguments. Must give type of signal generation." << endl;
        cout << "Input should be of form ./sig_gen [type] [frequency] [width]...";
        cout << "frequency and width are optional." << endl;
        exit(1);
    }

    // error: more than four arguments
    if (argc > 4) {
        cout << "Ignoring extraneous arguments..." << endl;
    }

    // determines which type of signal user wants to generate
    g_sig = determine_signal(argc, argv);

    // error: invalid waveform type
    if (g_sig < 0) {
        cout << "Must provide a valid type of waveform. --sine, --saw, --noise, --pulse, --impulse." << endl;
        exit(1);
    }

    // instantiate RtAudio object
    RtAudio audio;

    // frame size
    unsigned int bufferFrames = 512;
    unsigned int bufferBytes = 0;

    // check for audio devices
    if(audio.getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    audio.showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio.getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio.getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio.openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio.getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio.startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio.stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio.isStreamOpen())
            audio.closeStream();

    return 0;
}
<|endoftext|>


<commit_before>// willitwebgl.cpp
// Copyright (c) 2010, Ewen Cheslack-Postava
// All rights reserved.
//
// Originally based on visualinfo.c from glew. See http://glew.sourceforge.net/
// Copyright (C) Nate Robins, 1997
//               Michael Wimmer, 1999
//               Milan Ikits, 2002-2008
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//    * Neither the name of willitwebgl nor the names of its contributors
//      may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
//#include <GL/wglew.h>
#elif defined(__APPLE__)
#include <AGL/agl.h>
#else // Linux
#include <GL/glx.h>
#endif

#include <string>

#ifdef GLEW_MX
GLEWContext _glewctx;
#  define glewGetContext() (&_glewctx)
#  ifdef _WIN32
WGLEWContext _wglewctx;
#    define wglewGetContext() (&_wglewctx)
#  elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
GLXEWContext _glxewctx;
#    define glxewGetContext() (&_glxewctx)
#  endif
#endif /* GLEW_MX */

typedef struct GLContextStruct
{
#ifdef _WIN32
  HWND wnd;
  HDC dc;
  HGLRC rc;
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
  AGLContext ctx, octx;
#else
  Display* dpy;
  XVisualInfo* vi;
  GLXContext ctx;
  Window wnd;
  Colormap cmap;
#endif
} GLContext;

void InitContext (GLContext* ctx);
GLboolean CreateContext (GLContext* ctx);
void DestroyContext (GLContext* ctx);

void ReportInfo(const std::string& msg);

// Each check
enum CheckResult {
    PASS,
    WARNING,
    FAIL
};

// Each of these methods is a test for WebGL.  If any of them fails, WebGL
// almost certainly won't work.

CheckResult CheckInit();
CheckResult CheckDestroy();
CheckResult CheckVersion();
CheckResult CheckShaderVersion();

// To run tests, we make one long list and the main method just checks them in
// order.
typedef CheckResult(*WebGLCheck)();
WebGLCheck webgl_checks[] =
{
    CheckInit,
    CheckVersion,
    CheckShaderVersion,
    CheckDestroy,
    NULL
};

GLContext ctx;
// Shared buffer for generating messages for convenience.
char msg_buf[2048];

int main(int argc, char** argv) {
    GLenum err;

    for(WebGLCheck* check = webgl_checks; *check != NULL; check++) {
        (*check)();
    }

    return 0;
}

// Report information to the user.
void ReportInfo(const std::string& msg) {
    // FIXME This should use GUI output if possible since the user likely isn't
    // running from the command line.
    fprintf(stdout, "%s\n", msg.c_str());
}

#if defined(_WIN32)

void InitContext (GLContext* ctx)
{
  ctx->wnd = NULL;
  ctx->dc = NULL;
  ctx->rc = NULL;
}

GLboolean CreateContext (GLContext* ctx)
{
  WNDCLASS wc;
  PIXELFORMATDESCRIPTOR pfd;
  /* check for input */
  if (NULL == ctx) return GL_TRUE;
  /* register window class */
  ZeroMemory(&wc, sizeof(WNDCLASS));
  wc.hInstance = GetModuleHandle(NULL);
  wc.lpfnWndProc = DefWindowProc;
  wc.lpszClassName = "GLEW";
  if (0 == RegisterClass(&wc)) return GL_TRUE;
  /* create window */
  ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
                          GetModuleHandle(NULL), NULL);
  if (NULL == ctx->wnd) return GL_TRUE;
  /* get the device context */
  ctx->dc = GetDC(ctx->wnd);
  if (NULL == ctx->dc) return GL_TRUE;
  /* find pixel format */
  ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
  if (visual == -1) /* find default */
  {
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    visual = ChoosePixelFormat(ctx->dc, &pfd);
    if (0 == visual) return GL_TRUE;
  }
  /* set the pixel format for the dc */
  if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE;
  /* create rendering context */
  ctx->rc = wglCreateContext(ctx->dc);
  if (NULL == ctx->rc) return GL_TRUE;
  if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL == ctx) return;
  if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL);
  if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext());
  if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
  if (NULL != ctx->wnd) DestroyWindow(ctx->wnd);
  UnregisterClass("GLEW", GetModuleHandle(NULL));
}

/* ------------------------------------------------------------------------ */

#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)

void InitContext (GLContext* ctx)
{
  ctx->ctx = NULL;
  ctx->octx = NULL;
}

GLboolean CreateContext (GLContext* ctx)
{
  int attrib[] = { AGL_RGBA, AGL_NONE };
  AGLPixelFormat pf;
  /* check input */
  if (NULL == ctx) return GL_TRUE;
  /*int major, minor;
  SetPortWindowPort(wnd);
  aglGetVersion(&major, &minor);
  fprintf(stderr, "GL %d.%d\n", major, minor);*/
  pf = aglChoosePixelFormat(NULL, 0, attrib);
  if (NULL == pf) return GL_TRUE;
  ctx->ctx = aglCreateContext(pf, NULL);
  if (NULL == ctx->ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE;
  aglDestroyPixelFormat(pf);
  /*aglSetDrawable(ctx, GetWindowPort(wnd));*/
  ctx->octx = aglGetCurrentContext();
  if (GL_FALSE == aglSetCurrentContext(ctx->ctx)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL == ctx) return;
  aglSetCurrentContext(ctx->octx);
  if (NULL != ctx->ctx) aglDestroyContext(ctx->ctx);
}

/* ------------------------------------------------------------------------ */

#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */

char* display = NULL;

void InitContext (GLContext* ctx)
{
  ctx->dpy = NULL;
  ctx->vi = NULL;
  ctx->ctx = NULL;
  ctx->wnd = 0;
  ctx->cmap = 0;
}

GLboolean CreateContext (GLContext* ctx)
{
  int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
  int erb, evb;
  XSetWindowAttributes swa;
  /* check input */
  if (NULL == ctx) return GL_TRUE;
  /* open display */
  ctx->dpy = XOpenDisplay(display);
  if (NULL == ctx->dpy) return GL_TRUE;
  /* query for glx */
  if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE;
  /* choose visual */
  ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib);
  if (NULL == ctx->vi) return GL_TRUE;
  /* create context */
  ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True);
  if (NULL == ctx->ctx) return GL_TRUE;
  /* create window */
  /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/
  ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
                              ctx->vi->visual, AllocNone);
  swa.border_pixel = 0;
  swa.colormap = ctx->cmap;
  ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
                           0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual,
                           CWBorderPixel | CWColormap, &swa);
  /* make context current */
  if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx);
  if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd);
  if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap);
  if (NULL != ctx->vi) XFree(ctx->vi);
  if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy);
}

#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */

CheckResult CheckInit() {
    InitContext(&ctx);
    if (GL_TRUE == CreateContext(&ctx))
    {
        ReportInfo("Error: CreateContext failed.");
        DestroyContext(&ctx);
        return FAIL;
    }

    return PASS;
}

CheckResult CheckDestroy() {
    DestroyContext(&ctx);
    return PASS;
}

// Helper method for checking versions.  Tries to parse the beginning of a
// string as a version number, returning a .
bool ParseVersion(const char* str, int* major, int* minor) {
    int _major, _minor;
    int matched = sscanf(str, "%d.%d", &_major, &_minor);

    if (matched < 2)
        return false;

    if (major) *major = _major;
    if (minor) *minor = _minor;

    return true;
}

CheckResult CheckVersion() {
    int required_major = 2, required_minor = 0;

    int major, minor;
    const char* vers = (const char*)glGetString(GL_VERSION);
    if (vers == NULL) {
        ReportInfo("Error: Couldn't get GL_VERSION.");
        return FAIL;
    }

    bool parsed = ParseVersion(vers, &major, &minor);
    if (!parsed) {
        sprintf(msg_buf, "Unable to parse GL version: %s", vers);
        ReportInfo(msg_buf);
        return FAIL;
    }

    if (major < required_major ||
        (major == required_major && minor < required_minor)) {
        sprintf(msg_buf, "Require GL version %d.%d, have version %d.%d", required_major, required_minor, major, minor);
        ReportInfo(msg_buf);
        return FAIL;
    }

    return PASS;
}

CheckResult CheckShaderVersion() {
    int required_major = 1, required_minor = 20;

    int major, minor;
    const char* vers = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
    if (vers == NULL) {
        ReportInfo("Error: Couldn't get GL_SHADING_LANGUAGE_VERSION.");
        return FAIL;
    }

    bool parsed = ParseVersion(vers, &major, &minor);
    if (!parsed) {
        sprintf(msg_buf, "Unable to parse GL shading language version: %s", vers);
        ReportInfo(msg_buf);
        return FAIL;
    }

    if (major < required_major ||
        (major == required_major && minor < required_minor)) {
        sprintf(msg_buf, "Require GL shading language version %d.%d, have version %d.%d", required_major, required_minor, major, minor);
        ReportInfo(msg_buf);
        return FAIL;
    }

    return PASS;
}
<commit_msg>Bail out if a check fails, report success after loop of all checks is finished.<commit_after>// willitwebgl.cpp
// Copyright (c) 2010, Ewen Cheslack-Postava
// All rights reserved.
//
// Originally based on visualinfo.c from glew. See http://glew.sourceforge.net/
// Copyright (C) Nate Robins, 1997
//               Michael Wimmer, 1999
//               Milan Ikits, 2002-2008
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//    * Neither the name of willitwebgl nor the names of its contributors
//      may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
//#include <GL/wglew.h>
#elif defined(__APPLE__)
#include <AGL/agl.h>
#else // Linux
#include <GL/glx.h>
#endif

#include <string>

#ifdef GLEW_MX
GLEWContext _glewctx;
#  define glewGetContext() (&_glewctx)
#  ifdef _WIN32
WGLEWContext _wglewctx;
#    define wglewGetContext() (&_wglewctx)
#  elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
GLXEWContext _glxewctx;
#    define glxewGetContext() (&_glxewctx)
#  endif
#endif /* GLEW_MX */

typedef struct GLContextStruct
{
#ifdef _WIN32
  HWND wnd;
  HDC dc;
  HGLRC rc;
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
  AGLContext ctx, octx;
#else
  Display* dpy;
  XVisualInfo* vi;
  GLXContext ctx;
  Window wnd;
  Colormap cmap;
#endif
} GLContext;

void InitContext (GLContext* ctx);
GLboolean CreateContext (GLContext* ctx);
void DestroyContext (GLContext* ctx);

void ReportInfo(const std::string& msg);

// Each check
enum CheckResult {
    PASS,
    WARNING,
    FAIL
};

// Each of these methods is a test for WebGL.  If any of them fails, WebGL
// almost certainly won't work.

CheckResult CheckInit();
CheckResult CheckDestroy();
CheckResult CheckVersion();
CheckResult CheckShaderVersion();

// To run tests, we make one long list and the main method just checks them in
// order.
typedef CheckResult(*WebGLCheck)();
WebGLCheck webgl_checks[] =
{
    CheckInit,
    CheckVersion,
    CheckShaderVersion,
    CheckDestroy,
    NULL
};

GLContext ctx;
// Shared buffer for generating messages for convenience.
char msg_buf[2048];

int main(int argc, char** argv) {
    GLenum err;

    for(WebGLCheck* check = webgl_checks; *check != NULL; check++) {
        CheckResult result = (*check)();
        if (result == FAIL) {
            DestroyContext(&ctx);
            return -1;
        }
    }

    ReportInfo("Passed all checks, you should be able to run WebGL!");

    return 0;
}

// Report information to the user.
void ReportInfo(const std::string& msg) {
    // FIXME This should use GUI output if possible since the user likely isn't
    // running from the command line.
    fprintf(stdout, "%s\n", msg.c_str());
}

#if defined(_WIN32)

void InitContext (GLContext* ctx)
{
  ctx->wnd = NULL;
  ctx->dc = NULL;
  ctx->rc = NULL;
}

GLboolean CreateContext (GLContext* ctx)
{
  WNDCLASS wc;
  PIXELFORMATDESCRIPTOR pfd;
  /* check for input */
  if (NULL == ctx) return GL_TRUE;
  /* register window class */
  ZeroMemory(&wc, sizeof(WNDCLASS));
  wc.hInstance = GetModuleHandle(NULL);
  wc.lpfnWndProc = DefWindowProc;
  wc.lpszClassName = "GLEW";
  if (0 == RegisterClass(&wc)) return GL_TRUE;
  /* create window */
  ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
                          GetModuleHandle(NULL), NULL);
  if (NULL == ctx->wnd) return GL_TRUE;
  /* get the device context */
  ctx->dc = GetDC(ctx->wnd);
  if (NULL == ctx->dc) return GL_TRUE;
  /* find pixel format */
  ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
  if (visual == -1) /* find default */
  {
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    visual = ChoosePixelFormat(ctx->dc, &pfd);
    if (0 == visual) return GL_TRUE;
  }
  /* set the pixel format for the dc */
  if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE;
  /* create rendering context */
  ctx->rc = wglCreateContext(ctx->dc);
  if (NULL == ctx->rc) return GL_TRUE;
  if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL == ctx) return;
  if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL);
  if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext());
  if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
  if (NULL != ctx->wnd) DestroyWindow(ctx->wnd);
  UnregisterClass("GLEW", GetModuleHandle(NULL));
}

/* ------------------------------------------------------------------------ */

#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)

void InitContext (GLContext* ctx)
{
  ctx->ctx = NULL;
  ctx->octx = NULL;
}

GLboolean CreateContext (GLContext* ctx)
{
  int attrib[] = { AGL_RGBA, AGL_NONE };
  AGLPixelFormat pf;
  /* check input */
  if (NULL == ctx) return GL_TRUE;
  /*int major, minor;
  SetPortWindowPort(wnd);
  aglGetVersion(&major, &minor);
  fprintf(stderr, "GL %d.%d\n", major, minor);*/
  pf = aglChoosePixelFormat(NULL, 0, attrib);
  if (NULL == pf) return GL_TRUE;
  ctx->ctx = aglCreateContext(pf, NULL);
  if (NULL == ctx->ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE;
  aglDestroyPixelFormat(pf);
  /*aglSetDrawable(ctx, GetWindowPort(wnd));*/
  ctx->octx = aglGetCurrentContext();
  if (GL_FALSE == aglSetCurrentContext(ctx->ctx)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL == ctx) return;
  aglSetCurrentContext(ctx->octx);
  if (NULL != ctx->ctx) aglDestroyContext(ctx->ctx);
}

/* ------------------------------------------------------------------------ */

#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */

char* display = NULL;

void InitContext (GLContext* ctx)
{
  ctx->dpy = NULL;
  ctx->vi = NULL;
  ctx->ctx = NULL;
  ctx->wnd = 0;
  ctx->cmap = 0;
}

GLboolean CreateContext (GLContext* ctx)
{
  int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
  int erb, evb;
  XSetWindowAttributes swa;
  /* check input */
  if (NULL == ctx) return GL_TRUE;
  /* open display */
  ctx->dpy = XOpenDisplay(display);
  if (NULL == ctx->dpy) return GL_TRUE;
  /* query for glx */
  if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE;
  /* choose visual */
  ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib);
  if (NULL == ctx->vi) return GL_TRUE;
  /* create context */
  ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True);
  if (NULL == ctx->ctx) return GL_TRUE;
  /* create window */
  /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/
  ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
                              ctx->vi->visual, AllocNone);
  swa.border_pixel = 0;
  swa.colormap = ctx->cmap;
  ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
                           0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual,
                           CWBorderPixel | CWColormap, &swa);
  /* make context current */
  if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE;
  return GL_FALSE;
}

void DestroyContext (GLContext* ctx)
{
  if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx);
  if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd);
  if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap);
  if (NULL != ctx->vi) XFree(ctx->vi);
  if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy);
}

#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */

CheckResult CheckInit() {
    InitContext(&ctx);
    if (GL_TRUE == CreateContext(&ctx))
    {
        ReportInfo("Error: CreateContext failed.");
        DestroyContext(&ctx);
        return FAIL;
    }

    return PASS;
}

CheckResult CheckDestroy() {
    DestroyContext(&ctx);
    return PASS;
}

// Helper method for checking versions.  Tries to parse the beginning of a
// string as a version number, returning a .
bool ParseVersion(const char* str, int* major, int* minor) {
    int _major, _minor;
    int matched = sscanf(str, "%d.%d", &_major, &_minor);

    if (matched < 2)
        return false;

    if (major) *major = _major;
    if (minor) *minor = _minor;

    return true;
}

CheckResult CheckVersion() {
    int required_major = 2, required_minor = 0;

    int major, minor;
    const char* vers = (const char*)glGetString(GL_VERSION);
    if (vers == NULL) {
        ReportInfo("Error: Couldn't get GL_VERSION.");
        return FAIL;
    }

    bool parsed = ParseVersion(vers, &major, &minor);
    if (!parsed) {
        sprintf(msg_buf, "Unable to parse GL version: %s", vers);
        ReportInfo(msg_buf);
        return FAIL;
    }

    if (major < required_major ||
        (major == required_major && minor < required_minor)) {
        sprintf(msg_buf, "Require GL version %d.%d, have version %d.%d", required_major, required_minor, major, minor);
        ReportInfo(msg_buf);
        return FAIL;
    }

    return PASS;
}

CheckResult CheckShaderVersion() {
    int required_major = 1, required_minor = 20;

    int major, minor;
    const char* vers = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
    if (vers == NULL) {
        ReportInfo("Error: Couldn't get GL_SHADING_LANGUAGE_VERSION.");
        return FAIL;
    }

    bool parsed = ParseVersion(vers, &major, &minor);
    if (!parsed) {
        sprintf(msg_buf, "Unable to parse GL shading language version: %s", vers);
        ReportInfo(msg_buf);
        return FAIL;
    }

    if (major < required_major ||
        (major == required_major && minor < required_minor)) {
        sprintf(msg_buf, "Require GL shading language version %d.%d, have version %d.%d", required_major, required_minor, major, minor);
        ReportInfo(msg_buf);
        return FAIL;
    }

    return PASS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/common/pref_names.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/ui/tab_contents/per_tab_prefs_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
#include "content/browser/tab_contents/test_tab_contents.h"
#include "content/test/test_browser_thread.h"

using content::BrowserThread;

class TestPerTabPrefsTabHelper : public PerTabPrefsTabHelper {
 public:
  explicit TestPerTabPrefsTabHelper(TabContentsWrapper* tab_contents)
      : PerTabPrefsTabHelper(tab_contents),
        was_override_web_prefernces_called_(false) {
  }
  virtual ~TestPerTabPrefsTabHelper() { }

  virtual void OverrideWebPreferences(WebPreferences* prefs) OVERRIDE {
    was_override_web_prefernces_called_ = true;
    PerTabPrefsTabHelper::OverrideWebPreferences(prefs);
  }

  void NotifyRenderViewCreated() {
    RenderViewCreated(NULL);
  }

  bool was_override_web_prefernces_called() {
    return was_override_web_prefernces_called_;
  }

 private:
  bool was_override_web_prefernces_called_;
};

class PerTabPrefsTabHelperTest : public TabContentsWrapperTestHarness {
 public:
  PerTabPrefsTabHelperTest()
      : TabContentsWrapperTestHarness(),
        ui_thread_(BrowserThread::UI, &message_loop_) {}

  virtual ~PerTabPrefsTabHelperTest() {}

  TabContentsWrapper* contents_wrapper2() {
    return contents_wrapper2_.get();
  }

  void SetContents2(TestTabContents* contents) {
    contents_wrapper2_.reset(
        contents ? new TabContentsWrapper(contents) : NULL);
  }

 protected:
  virtual void SetUp() OVERRIDE {
    TabContentsWrapperTestHarness::SetUp();
    SetContents2(CreateTestTabContents());
  }

  virtual void TearDown() OVERRIDE {
    contents_wrapper2_.reset();
    TabContentsWrapperTestHarness::TearDown();
  }

 private:
  content::TestBrowserThread ui_thread_;
  scoped_ptr<TabContentsWrapper> contents_wrapper2_;

  DISALLOW_COPY_AND_ASSIGN(PerTabPrefsTabHelperTest);
};

TEST_F(PerTabPrefsTabHelperTest, PerTabJavaScriptEnabled) {
  const char* key = prefs::kWebKitJavascriptEnabled;
  PrefService* prefs1 = contents_wrapper()->per_tab_prefs_tab_helper()->prefs();
  PrefService* prefs2 =
      contents_wrapper2()->per_tab_prefs_tab_helper()->prefs();
  const bool initial_value = prefs1->GetBoolean(key);
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs1->SetBoolean(key, !initial_value);
  EXPECT_EQ(!initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs1->SetBoolean(key, initial_value);
  EXPECT_EQ(initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs2->SetBoolean(key, !initial_value);
  EXPECT_EQ(initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(!initial_value, prefs2->GetBoolean(key));
}

TEST_F(PerTabPrefsTabHelperTest, OverridePrefsOnViewCreation) {
  TestPerTabPrefsTabHelper* test_prefs_helper = new TestPerTabPrefsTabHelper(
      contents_wrapper());
  contents_wrapper()->per_tab_prefs_tab_helper_.reset(test_prefs_helper);
  EXPECT_EQ(false, test_prefs_helper->was_override_web_prefernces_called());
  test_prefs_helper->NotifyRenderViewCreated();
  EXPECT_EQ(true, test_prefs_helper->was_override_web_prefernces_called());
}
<commit_msg>A build fix for gcc 4.5+. GCC 4.5+ somehow causes compilation errors while compiling EXPECT_EQ(false,...) and EXPECT_EQ(true,...). This change just replaces EXPECT_EQ(false,...) with EXPECT_FALSE(...), and replaces EXPECT_EQ(true,...) with EXPECT_TRUE(...), respectively.<commit_after>// Copyright (c) 2011 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/common/pref_names.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/ui/tab_contents/per_tab_prefs_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
#include "content/browser/tab_contents/test_tab_contents.h"
#include "content/test/test_browser_thread.h"

using content::BrowserThread;

class TestPerTabPrefsTabHelper : public PerTabPrefsTabHelper {
 public:
  explicit TestPerTabPrefsTabHelper(TabContentsWrapper* tab_contents)
      : PerTabPrefsTabHelper(tab_contents),
        was_override_web_prefernces_called_(false) {
  }
  virtual ~TestPerTabPrefsTabHelper() { }

  virtual void OverrideWebPreferences(WebPreferences* prefs) OVERRIDE {
    was_override_web_prefernces_called_ = true;
    PerTabPrefsTabHelper::OverrideWebPreferences(prefs);
  }

  void NotifyRenderViewCreated() {
    RenderViewCreated(NULL);
  }

  bool was_override_web_prefernces_called() {
    return was_override_web_prefernces_called_;
  }

 private:
  bool was_override_web_prefernces_called_;
};

class PerTabPrefsTabHelperTest : public TabContentsWrapperTestHarness {
 public:
  PerTabPrefsTabHelperTest()
      : TabContentsWrapperTestHarness(),
        ui_thread_(BrowserThread::UI, &message_loop_) {}

  virtual ~PerTabPrefsTabHelperTest() {}

  TabContentsWrapper* contents_wrapper2() {
    return contents_wrapper2_.get();
  }

  void SetContents2(TestTabContents* contents) {
    contents_wrapper2_.reset(
        contents ? new TabContentsWrapper(contents) : NULL);
  }

 protected:
  virtual void SetUp() OVERRIDE {
    TabContentsWrapperTestHarness::SetUp();
    SetContents2(CreateTestTabContents());
  }

  virtual void TearDown() OVERRIDE {
    contents_wrapper2_.reset();
    TabContentsWrapperTestHarness::TearDown();
  }

 private:
  content::TestBrowserThread ui_thread_;
  scoped_ptr<TabContentsWrapper> contents_wrapper2_;

  DISALLOW_COPY_AND_ASSIGN(PerTabPrefsTabHelperTest);
};

TEST_F(PerTabPrefsTabHelperTest, PerTabJavaScriptEnabled) {
  const char* key = prefs::kWebKitJavascriptEnabled;
  PrefService* prefs1 = contents_wrapper()->per_tab_prefs_tab_helper()->prefs();
  PrefService* prefs2 =
      contents_wrapper2()->per_tab_prefs_tab_helper()->prefs();
  const bool initial_value = prefs1->GetBoolean(key);
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs1->SetBoolean(key, !initial_value);
  EXPECT_EQ(!initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs1->SetBoolean(key, initial_value);
  EXPECT_EQ(initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(initial_value, prefs2->GetBoolean(key));

  prefs2->SetBoolean(key, !initial_value);
  EXPECT_EQ(initial_value, prefs1->GetBoolean(key));
  EXPECT_EQ(!initial_value, prefs2->GetBoolean(key));
}

TEST_F(PerTabPrefsTabHelperTest, OverridePrefsOnViewCreation) {
  TestPerTabPrefsTabHelper* test_prefs_helper = new TestPerTabPrefsTabHelper(
      contents_wrapper());
  contents_wrapper()->per_tab_prefs_tab_helper_.reset(test_prefs_helper);
  EXPECT_FALSE(test_prefs_helper->was_override_web_prefernces_called());
  test_prefs_helper->NotifyRenderViewCreated();
  EXPECT_TRUE(test_prefs_helper->was_override_web_prefernces_called());
}
<|endoftext|>