<commit_before>/* cclive
 * Copyright (C) 2010-2011  Toni Gundogdu <legatvs@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <ccapplication>
#include <ccquvi>

using namespace cc;

int main(int argc, char *argv[])
{
  application app;
  int rc = 0; // OK.

  try
    {
      rc = app.exec(argc,argv);
    }

  // Thrown by quvi::query constructor (e.g. quvi_init failure).
  catch (const quvi::error& e)
    {
      std::clog << "libquvi: error: " << e.what() << std::endl;
    }

  // Thrown by boost (e.g. cc::go_background failure).
  catch (const std::runtime_error& e)
    {
      std::clog << "error: " << e.what() << std::endl;
    }

  return rc;
}

// vim: set ts=2 sw=2 tw=72 expandtab:
<commit_msg>main: Use exit_status, have caught exceptions set exit status<commit_after>/* cclive
 * Copyright (C) 2010-2011  Toni Gundogdu <legatvs@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <ccapplication>
#include <ccquvi>

using namespace cc;

int main(int argc, char *argv[])
{
  application::exit_status es = application::ok;
  application app;
  try
    {
      es = app.exec(argc, argv);
    }
  // Thrown by quvi::query constructor (e.g. quvi_init failure).
  catch (const quvi::error& e)
    {
      std::clog << "libquvi: error: " << e.what() << std::endl;
      es = application::error;
    }
  // Thrown by boost (e.g. cc::go_background failure).
  catch (const std::runtime_error& e)
    {
      std::clog << "error: " << e.what() << std::endl;
      es = application::error;
    }
  return es;
}

// vim: set ts=2 sw=2 tw=72 expandtab:
<|endoftext|>


<commit_before>#ifndef DICE_CHECKED_HPP_
#define DICE_CHECKED_HPP_

#include <limits>
#include <stdexcept>

namespace dice
{
    // Check for arithmetic errors
    template<typename T, bool is_signed = std::numeric_limits<T>::is_signed>
    class checked;

    // signed value specialization
    template<typename T>
    class checked<T, true>
    {
    public:
        checked() {}
        checked(const T& value) : value_(value) {}

        // allow copy
        checked(const checked&) = default;
        checked& operator=(const checked&) = default;

        // allow move
        checked(checked&&) = default;
        checked& operator=(checked&&) = default;

        /** Compute addition of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the addition as a checked type
         */
        auto operator+(const T& other_value) const
        {
            using namespace std;

            if (other_value > 0 && value_ > max() - other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            if (other_value < 0 && value_ < min() - other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            return checked<T>{ value_ + other_value };
        }

        /** Compute subtraction of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the subtraction as a checked type
         */
        auto operator-(const T& other_value) const
        {
            using namespace std;

            if (other_value < 0 && value_ > max() + other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            if (other_value > 0 && value_ < min() + other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            return checked<T>{ value_ - other_value };
        }

        /** Compute multiplication of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the multiplication as a checked type
         */
        auto operator*(const T& other_value) const
        {
            using namespace std;

            auto diff = max() + min();
            if (diff < 0)
            {
                if (value_ == -1 && other_value == min() ||
                    value_ == min() && other_value == -1)
                {
                    throw std::overflow_error{
                        to_string(value_) + " * " + to_string(other_value)
                    };
                }
            }
            else if (diff > 0)
            {
                if (value_ == -1 && other_value == max() ||
                    value_ == max() && other_value == -1)
                {
                    throw std::underflow_error{
                        to_string(value_) + " * " + to_string(other_value)
                    };
                }
            }

            if (other_value != 0 && value_ != 0 && other_value != -1)
            {
                // check whether there would be an overflow error
                if (other_value > 0 && value_ > max() / other_value ||
                    other_value < 0 && value_ < max() / other_value)
                {
                    throw std::overflow_error{
                        to_string(value_) + " * " + to_string(other_value) };
                }

                // check whether there would be an underflow error
                if (other_value > 0 && value_ < min() / other_value ||
                    other_value < 0 && value_ > min() / other_value)
                {
                    throw std::underflow_error{
                        to_string(value_) + " * " + to_string(other_value) };
                }
            }

            return checked<T>{ value_ * other_value };
        }

        /** Compute division of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If the other_value is zero, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the division as a checked type
         */
        auto operator/(const T& other_value) const
        {
            using namespace std;

            if (other_value == 0)
            {
                throw std::overflow_error{ "Division by zero: " +
                    to_string(value_) + " / 0" };
            }

            auto diff = max() + min();
            if (diff < 0)
            {
                if (value_ == min() && other_value == -1)
                {
                    throw std::overflow_error{
                        to_string(value_) + " / " + to_string(other_value)
                    };
                }
            }
            else if (diff > 0)
            {
                if (value_ == max() && other_value == -1)
                {
                    throw std::underflow_error{
                        to_string(value_) + " / " + to_string(other_value)
                    };
                }
            }

            return checked<T>{ value_ / other_value };
        }

        /** Compute unary minus of the value.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @return result of the unary minus as a checked type
         */
        auto operator-() const
        {
            using namespace std;

            auto diff = max() + min();
            if (diff < 0 && value_ == min())
            {
                throw std::overflow_error{ "-" + to_string(value_) };
            }
            else if (diff > 0 && value_ == max())
            {
                throw std::underflow_error{ "-" + to_string(value_) };
            }
            return checked<T>{ -value_ };
        }

        // cast to type T
        operator T() const
        {
            return value_;
        }

        // explicit value getter/setter
        T& value()
        {
            return value_;
        }

        const T& value() const
        {
            return value_;
        }
    private:
        T value_;

        static constexpr T max()
        {
            return std::numeric_limits<T>::max();
        }

        static constexpr T min()
        {
            return std::numeric_limits<T>::min();
        }
    };

    // unsigned value specialization
    template<typename T>
    class checked<T, false>
    {
    public:
        checked() {}
        checked(const T& value) : value_(value) {}

        // allow copy
        checked(const checked&) = default;
        checked& operator=(const checked&) = default;

        // allow move
        checked(checked&&) = default;
        checked& operator=(checked&&) = default;

        /** Compute addition of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the addition as a checked type
         */
        auto operator+(const T& other_value) const
        {
            using namespace std;

            if (value_ > max() - other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            return checked<T>{ value_ + other_value };
        }

        /** Compute subtraction of the 2 values.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the subtraction as a checked type
         */
        auto operator-(const T& other_value) const
        {
            using namespace std;

            if (value_ <  other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            return checked<T>{ value_ - other_value };
        }

        /** Compute multiplication of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the multiplication as a checked type
         */
        auto operator*(const T& other_value) const
        {
            using namespace std;

            // check whether there would be an overflow error
            if (other_value != 0 && value_ > max() / other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " * " + to_string(other_value) };
            }

            return checked<T>{ value_ * other_value };
        }

        /** Compute division of the 2 values.
         * If the other_value is zero, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the division as a checked type
         */
        auto operator/(const T& other_value) const
        {
            using namespace std;

            if (other_value == 0)
            {
                throw std::overflow_error{ "Division by zero: " +
                    to_string(value_) + " / 0" };
            }

            return checked<T>{ value_ / other_value };
        }

        /** Compute unary minus of the value.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @return result of the unary minus as a checked type
         */
        auto operator-() const
        {
            using namespace std;

            if (value_ != 0)
            {
                throw std::underflow_error{ "-" + to_string(value_) };
            }
            return checked<T>{ 0 };
        }

        // cast to type T
        operator T() const
        {
            return value_;
        }

        // explicit value getter/setter
        T& value()
        {
            return value_;
        }

        const T& value() const
        {
            return value_;
        }
    private:
        T value_;

        static constexpr T max()
        {
            return std::numeric_limits<T>::max();
        }
    };
}

#endif // DICE_CHECKED_HPP_<commit_msg>Add factory functions<commit_after>#ifndef DICE_CHECKED_HPP_
#define DICE_CHECKED_HPP_

#include <limits>
#include <stdexcept>

namespace dice
{
    // Check for arithmetic errors
    template<
        typename T,
        bool is_integral = std::numeric_limits<T>::is_integer,
        bool is_signed = std::numeric_limits<T>::is_signed>
    class checked
    {
    public:
        template<typename ValueType>
        static auto make(ValueType&& value)
        {
            return std::forward<ValueType>(value);
        }
    };

    // signed value specialization
    template<typename T>
    class checked<T, true, true>
    {
    public:
        template<typename ValueType>
        static auto make(ValueType&& value)
        {
            return checked{ std::forward<ValueType>(value) };
        }

        checked() {}
        checked(const T& value) : value_(value) {}

        // allow copy
        checked(const checked&) = default;
        checked& operator=(const checked&) = default;

        // allow move
        checked(checked&&) = default;
        checked& operator=(checked&&) = default;

        /** Compute addition of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the addition as a checked type
         */
        auto operator+(const T& other_value) const
        {
            using namespace std;

            if (other_value > 0 && value_ > max() - other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            if (other_value < 0 && value_ < min() - other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            return checked<T>{ value_ + other_value };
        }

        /** Compute subtraction of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the subtraction as a checked type
         */
        auto operator-(const T& other_value) const
        {
            using namespace std;

            if (other_value < 0 && value_ > max() + other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            if (other_value > 0 && value_ < min() + other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            return checked<T>{ value_ - other_value };
        }

        /** Compute multiplication of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the multiplication as a checked type
         */
        auto operator*(const T& other_value) const
        {
            using namespace std;

            auto diff = max() + min();
            if (diff < 0)
            {
                if ((value_ == -1 && other_value == min()) ||
                    (value_ == min() && other_value == -1))
                {
                    throw std::overflow_error{
                        to_string(value_) + " * " + to_string(other_value)
                    };
                }
            }
            else if (diff > 0)
            {
                if ((value_ == -1 && other_value == max()) ||
                    (value_ == max() && other_value == -1))
                {
                    throw std::underflow_error{
                        to_string(value_) + " * " + to_string(other_value)
                    };
                }
            }

            if (other_value != 0 && value_ != 0 && other_value != -1)
            {
                // check whether there would be an overflow error
                if ((other_value > 0 && value_ > max() / other_value) ||
                    (other_value < 0 && value_ < max() / other_value))
                {
                    throw std::overflow_error{
                        to_string(value_) + " * " + to_string(other_value) };
                }

                // check whether there would be an underflow error
                if ((other_value > 0 && value_ < min() / other_value) ||
                    (other_value < 0 && value_ > min() / other_value))
                {
                    throw std::underflow_error{
                        to_string(value_) + " * " + to_string(other_value) };
                }
            }

            return checked<T>{ value_ * other_value };
        }

        /** Compute division of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * If the other_value is zero, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the division as a checked type
         */
        auto operator/(const T& other_value) const
        {
            using namespace std;

            if (other_value == 0)
            {
                throw std::overflow_error{ "Division by zero: " +
                    to_string(value_) + " / 0" };
            }

            auto diff = max() + min();
            if (diff < 0)
            {
                if (value_ == min() && other_value == -1)
                {
                    throw std::overflow_error{
                        to_string(value_) + " / " + to_string(other_value)
                    };
                }
            }
            else if (diff > 0)
            {
                if (value_ == max() && other_value == -1)
                {
                    throw std::underflow_error{
                        to_string(value_) + " / " + to_string(other_value)
                    };
                }
            }

            return checked<T>{ value_ / other_value };
        }

        /** Compute unary minus of the value.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @return result of the unary minus as a checked type
         */
        auto operator-() const
        {
            using namespace std;

            auto diff = max() + min();
            if (diff < 0 && value_ == min())
            {
                throw std::overflow_error{ "-" + to_string(value_) };
            }
            else if (diff > 0 && value_ == max())
            {
                throw std::underflow_error{ "-" + to_string(value_) };
            }
            return checked<T>{ -value_ };
        }

        // cast to type T
        operator T() const
        {
            return value_;
        }

        // explicit value getter/setter
        T& value()
        {
            return value_;
        }

        const T& value() const
        {
            return value_;
        }
    private:
        T value_;

        static constexpr T max()
        {
            return std::numeric_limits<T>::max();
        }

        static constexpr T min()
        {
            return std::numeric_limits<T>::min();
        }
    };

    // unsigned value specialization
    template<typename T>
    class checked<T, true, false>
    {
    public:
        template<typename ValueType>
        static auto make(ValueType&& value)
        {
            return checked{ std::forward<ValueType>(value) };
        }

        checked() {}
        checked(const T& value) : value_(value) {}

        // allow copy
        checked(const checked&) = default;
        checked& operator=(const checked&) = default;

        // allow move
        checked(checked&&) = default;
        checked& operator=(checked&&) = default;

        /** Compute addition of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the addition as a checked type
         */
        auto operator+(const T& other_value) const
        {
            using namespace std;

            if (value_ > max() - other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " + " + to_string(other_value) };
            }

            return checked<T>{ value_ + other_value };
        }

        /** Compute subtraction of the 2 values.
         * If an uderflow occurs, the std::underflow_error is thrown.
         * @param other raw value
         * @return result of the subtraction as a checked type
         */
        auto operator-(const T& other_value) const
        {
            using namespace std;

            if (value_ <  other_value)
            {
                throw std::underflow_error{
                    to_string(value_) + " - " + to_string(other_value) };
            }

            return checked<T>{ value_ - other_value };
        }

        /** Compute multiplication of the 2 values.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the multiplication as a checked type
         */
        auto operator*(const T& other_value) const
        {
            using namespace std;

            // check whether there would be an overflow error
            if (other_value != 0 && value_ > max() / other_value)
            {
                throw std::overflow_error{
                    to_string(value_) + " * " + to_string(other_value) };
            }

            return checked<T>{ value_ * other_value };
        }

        /** Compute division of the 2 values.
         * If the other_value is zero, the std::overflow_error is thrown.
         * @param other raw value
         * @return result of the division as a checked type
         */
        auto operator/(const T& other_value) const
        {
            using namespace std;

            if (other_value == 0)
            {
                throw std::overflow_error{ "Division by zero: " +
                    to_string(value_) + " / 0" };
            }

            return checked<T>{ value_ / other_value };
        }

        /** Compute unary minus of the value.
         * If an overflow occurs, the std::overflow_error is thrown.
         * @return result of the unary minus as a checked type
         */
        auto operator-() const
        {
            using namespace std;

            if (value_ != 0)
            {
                throw std::underflow_error{ "-" + to_string(value_) };
            }
            return checked<T>{ 0 };
        }

        // cast to type T
        operator T() const
        {
            return value_;
        }

        // explicit value getter/setter
        T& value()
        {
            return value_;
        }

        const T& value() const
        {
            return value_;
        }
    private:
        T value_;

        static constexpr T max()
        {
            return std::numeric_limits<T>::max();
        }
    };

    template<typename T>
    auto make_checked(const T& value)
    {
        return checked<T>{ value };
    }
}

#endif // DICE_CHECKED_HPP_<|endoftext|>


<commit_before>/**
 * @file command.cpp
 * @brief Request command component
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/command.h"
#include "mega/base64.h"
#include "mega/megaclient.h"

namespace mega {
Command::Command()
{
    persistent = false;
    canceled = false;
    result = API_OK;
    client = NULL;
    tag = 0;
    batchSeparately = false;
    suppressSID = false;
}

Command::~Command()
{
}

void Command::cancel()
{
    canceled = true;
}

// returns completed command JSON string
const char* Command::getstring()
{
    return jsonWriter.getstring().c_str();
}

//return true when the response is an error, false otherwise (in that case it doesn't consume JSON chars)
bool Command::checkError(Error& errorDetails, JSON& json)
{
    error e;
    bool errorDetected = false;
    if (json.isNumericError(e))
    {
        // isNumericError already moved the pointer past the integer (name could imply this?)
        errorDetails.setErrorCode(e);
        errorDetected = true;
    }
    else
    {
        const char* ptr = json.pos;
        if (*ptr == ',')
        {
            ptr++;
        }

        if (strncmp(ptr, "{\"err\":", 7) == 0)
        {
            bool exit = false;
            json.enterobject();
            while (!exit)
            {
                switch (json.getnameid())
                {
                    case MAKENAMEID3('e', 'r', 'r'):
                        errorDetails.setErrorCode(static_cast<error>(json.getint()));
                        errorDetected = true;
                        break;
                    case 'u':
                        errorDetails.setUserStatus(json.getint());
                        break;
                    case 'l':
                        errorDetails.setLinkStatus(json.getint());
                        break;
                    case EOO:
                        exit = true;
                        break;
                    default:
                        json.storeobject();
                        break;
                }
            }
            json.leaveobject();
        }
    }

    // generic handling of errors for all commands below

    if (errorDetected && errorDetails == API_EPAYWALL)
    {
        client->activateoverquota(0, true);
    }

#ifdef ENABLE_SYNC
    if (errorDetected && errorDetails == API_EBUSINESSPASTDUE)
    {
        client->syncs.disableSyncs(BUSINESS_EXPIRED, false);
    }
#endif
    return errorDetected;
}

// cache urls and ips given in response to avoid further waiting for dns resolution
bool Command::cacheresolvedurls(const std::vector<string>& urls, std::vector<string>&& ips)
{
    // cache resolved URLs if received
    bool result = client->httpio->cacheresolvedurls(urls, std::move(ips));
    if (result == false)
    {
        assert(false);
        client->sendevent(99456, "Unpaired IPs received for URLs in this command");
    }
    return result;
}

// Store ips from response in the vector passed
bool Command::loadIpsFromJson(std::vector<string>& ips)
{
    if (client->json.enterarray()) // for each URL, there will be 2 IPs (IPv4 first, IPv6 second)
    {
        for (;;)
        {
            std::string ti;
            if (!client->json.storeobject(&ti))
            {
                break;
            }
            ips.push_back(ti);
        }
        client->json.leavearray();
        return true;
    }
    return false;
}

// add opcode
void Command::cmd(const char* cmd)
{
    jsonWriter.cmd(cmd);
}

void Command::notself(MegaClient *client)
{
    jsonWriter.notself(client);
}

// add comma separator unless first element
void Command::addcomma()
{
    jsonWriter.addcomma();
}

// add command argument name:value pair (FIXME: add proper JSON escaping)
void Command::arg(const char* name, const char* value, int quotes)
{
    jsonWriter.arg(name, value, quotes);
}

// binary data
void Command::arg(const char* name, const byte* value, int len)
{
    jsonWriter.arg(name, value, len);
}

void Command::arg(const char* name, NodeHandle h)
{
    jsonWriter.arg(name, h);
}

// 64-bit signed integer
void Command::arg(const char* name, m_off_t n)
{
    jsonWriter.arg(name, n);
}

// raw JSON data
void Command::appendraw(const char* s)
{
    jsonWriter.appendraw(s);
}

// raw JSON data with length specifier
void Command::appendraw(const char* s, int len)
{
    jsonWriter.appendraw(s, len);
}

// begin array
void Command::beginarray()
{
    jsonWriter.beginarray();
}

// begin array member
void Command::beginarray(const char* name)
{
    jsonWriter.beginarray(name);
}

// close array
void Command::endarray()
{
    jsonWriter.endarray();
}

// begin JSON object
void Command::beginobject()
{
    jsonWriter.beginobject();
}

void Command::beginobject(const char *name)
{
    jsonWriter.beginobject(name);
}

// end JSON object
void Command::endobject()
{
    jsonWriter.endobject();
}

// add integer
void Command::element(int n)
{
    jsonWriter.element(n);
}

// add handle (with size specifier)
void Command::element(handle h, int len)
{
    jsonWriter.element(h, len);
}

// add binary data
void Command::element(const byte* data, int len)
{
    jsonWriter.element(data, len);
}

void Command::element(const char *buf)
{
    jsonWriter.element(buf);
}

// open object
void Command::openobject()
{
    jsonWriter.openobject();
}

// close object
void Command::closeobject()
{
    jsonWriter.closeobject();
}

} // namespace

<commit_msg>SDK-2000. Provide methods to retrieve thumbnail/preview upload urls in the intermediate layer.<commit_after>/**
 * @file command.cpp
 * @brief Request command component
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega/command.h"
#include "mega/base64.h"
#include "mega/megaclient.h"

namespace mega {
Command::Command()
{
    persistent = false;
    canceled = false;
    result = API_OK;
    client = NULL;
    tag = 0;
    batchSeparately = false;
    suppressSID = false;
}

Command::~Command()
{
}

void Command::cancel()
{
    canceled = true;
}

// returns completed command JSON string
const char* Command::getstring()
{
    return jsonWriter.getstring().c_str();
}

//return true when the response is an error, false otherwise (in that case it doesn't consume JSON chars)
bool Command::checkError(Error& errorDetails, JSON& json)
{
    error e;
    bool errorDetected = false;
    if (json.isNumericError(e))
    {
        // isNumericError already moved the pointer past the integer (name could imply this?)
        errorDetails.setErrorCode(e);
        errorDetected = true;
    }
    else
    {
        const char* ptr = json.pos;
        if (*ptr == ',')
        {
            ptr++;
        }

        if (strncmp(ptr, "{\"err\":", 7) == 0)
        {
            bool exit = false;
            json.enterobject();
            while (!exit)
            {
                switch (json.getnameid())
                {
                    case MAKENAMEID3('e', 'r', 'r'):
                        errorDetails.setErrorCode(static_cast<error>(json.getint()));
                        errorDetected = true;
                        break;
                    case 'u':
                        errorDetails.setUserStatus(json.getint());
                        break;
                    case 'l':
                        errorDetails.setLinkStatus(json.getint());
                        break;
                    case EOO:
                        exit = true;
                        break;
                    default:
                        json.storeobject();
                        break;
                }
            }
            json.leaveobject();
        }
    }

    // generic handling of errors for all commands below

    if (errorDetected && errorDetails == API_EPAYWALL)
    {
        client->activateoverquota(0, true);
    }

#ifdef ENABLE_SYNC
    if (errorDetected && errorDetails == API_EBUSINESSPASTDUE)
    {
        client->syncs.disableSyncs(BUSINESS_EXPIRED, false);
    }
#endif
    return errorDetected;
}

// cache urls and ips given in response to avoid further waiting for dns resolution
bool Command::cacheresolvedurls(const std::vector<string>& urls, std::vector<string>&& ips)
{
    // cache resolved URLs if received
    bool result = client->httpio->cacheresolvedurls(urls, std::move(ips));
    if (result == false)
    {
        client->sendevent(99456, "Unpaired IPs received for URLs in this command");
    }
    return result;
}

// Store ips from response in the vector passed
bool Command::loadIpsFromJson(std::vector<string>& ips)
{
    if (client->json.enterarray()) // for each URL, there will be 2 IPs (IPv4 first, IPv6 second)
    {
        for (;;)
        {
            std::string ti;
            if (!client->json.storeobject(&ti))
            {
                break;
            }
            ips.push_back(ti);
        }
        client->json.leavearray();
        return true;
    }
    return false;
}

// add opcode
void Command::cmd(const char* cmd)
{
    jsonWriter.cmd(cmd);
}

void Command::notself(MegaClient *client)
{
    jsonWriter.notself(client);
}

// add comma separator unless first element
void Command::addcomma()
{
    jsonWriter.addcomma();
}

// add command argument name:value pair (FIXME: add proper JSON escaping)
void Command::arg(const char* name, const char* value, int quotes)
{
    jsonWriter.arg(name, value, quotes);
}

// binary data
void Command::arg(const char* name, const byte* value, int len)
{
    jsonWriter.arg(name, value, len);
}

void Command::arg(const char* name, NodeHandle h)
{
    jsonWriter.arg(name, h);
}

// 64-bit signed integer
void Command::arg(const char* name, m_off_t n)
{
    jsonWriter.arg(name, n);
}

// raw JSON data
void Command::appendraw(const char* s)
{
    jsonWriter.appendraw(s);
}

// raw JSON data with length specifier
void Command::appendraw(const char* s, int len)
{
    jsonWriter.appendraw(s, len);
}

// begin array
void Command::beginarray()
{
    jsonWriter.beginarray();
}

// begin array member
void Command::beginarray(const char* name)
{
    jsonWriter.beginarray(name);
}

// close array
void Command::endarray()
{
    jsonWriter.endarray();
}

// begin JSON object
void Command::beginobject()
{
    jsonWriter.beginobject();
}

void Command::beginobject(const char *name)
{
    jsonWriter.beginobject(name);
}

// end JSON object
void Command::endobject()
{
    jsonWriter.endobject();
}

// add integer
void Command::element(int n)
{
    jsonWriter.element(n);
}

// add handle (with size specifier)
void Command::element(handle h, int len)
{
    jsonWriter.element(h, len);
}

// add binary data
void Command::element(const byte* data, int len)
{
    jsonWriter.element(data, len);
}

void Command::element(const char *buf)
{
    jsonWriter.element(buf);
}

// open object
void Command::openobject()
{
    jsonWriter.openobject();
}

// close object
void Command::closeobject()
{
    jsonWriter.closeobject();
}

} // namespace

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <functional>

using namespace std;

namespace {

namespace io {

enum token_type {
  REG,
  NN
};

ofstream outfile;
ifstream infile;

void exit_ok() {
  infile.close();
  outfile.close();
  exit(0);
}

void exit_err(string const& error) {
  cerr << error;
  infile.close();
  outfile.close();
  exit(1);
}

void write_bins(char lhs, char rhs) {
  outfile.write(static_cast<char*>(&lhs), 1);
  outfile.write(static_cast<char*>(&rhs), 1);
  if (outfile.fail()) {
    exit_err("Error writing to disk");
  }
}

int xtoi(string const& x) {
  try {
    return stoi(x, 0, 16);
  } catch (exception &e) {
    return -1;
  }
}

string next_token() {
  string value;
  io::infile >> value;
  if (!io::infile) {
    io::exit_ok();
  }
  return value;
}

void tok2n(string const& name, string&& value, char& n) {
  int target = xtoi(value);
  if (0 > target || 0xF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-F]\n");
  }
  n = target;
}

void tok2nn(string const& name, string&& value, char& nn) {
  int target = xtoi(value);
  if (0 > target || 0xFF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-FF]\n");
  }
  nn = target;
}

void tok2nnn(string const& name, string&& value, char& lhs, char& rhs) {
  int target = xtoi(value);
  if (0 > target || 0xFFF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-FFF]\n");
  }
  lhs = target >> 8;
  rhs = target & 0xFF;
}

void tok2reg(string const& name, string&& value, char& reg) {
  if (value.at(0) != 'r') {
    exit_err("Error: " + name + " needs to be supplied with a register r[0-F]\n");
  }

  int target = xtoi(value.substr(1));
  if (0 > target || 0xF < target) {
    exit_err("Error: " + name + " needs to be supplied with a register r[0-F]\n");
  }
  reg = target;
}

void tok2reg_or_nn(string const& name, string&& value, char& reg_or_nn, io::token_type& t) {
  if (value.at(0) == 'r') {
    t = REG;
    tok2reg(name, forward<string>(value), reg_or_nn);
  } else {
    t = NN;
    tok2nn(name, forward<string>(value), reg_or_nn);
  }
}

} // io

namespace op {

// These variables are shared between all below functions
char lhs;
char rhs;
char rhs2;
io::token_type t;

inline void OP(char lhs, char rhs) { io::write_bins(lhs, rhs); }

inline void R(string const& name, char lop, char rop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::write_bins(lop + lhs, rop);
}

inline void RR(string const& name, char lop, char rop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg(name, io::next_token(), rhs);
  io::write_bins(lop + lhs, (rhs << 4) + rop);
}

inline void NNN(string const& name, char op) {
  io::tok2nnn(name, io::next_token(), lhs, rhs);
  io::write_bins(op + lhs, rhs);
}

inline void RNN(string const& name, char lop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2nn(name, io::next_token(), rhs);
  io::write_bins(lop + lhs, rhs);
}

inline void RRN(string const& name, char lop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg(name, io::next_token(), rhs);
  io::tok2n(name, io::next_token(), rhs2);
  io::write_bins(lop + lhs, (rhs << 4) + rhs2);
}

inline void RV(string const& name, char nnop, char rlop, char rrop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg_or_nn(name, io::next_token(), rhs, t);
  if (t == io::NN)       { io::write_bins(nnop + lhs, rhs); }
  else if (t == io::REG) { io::write_bins(rlop + lhs, (rhs << 4) + rrop); }
  else                   { io::exit_err(name + ": Unknown type\n"); }
}

} // op

int help(string program_name) {
  cerr
    << "Usage: " << program_name << " FILE\n\n"
    << "Available commands\n"
    << "CLS          - 0x00E0\n"
    << "RET          - 0x00EE\n"
    << "JMP  NNN     - 0x1NNN\n"
    << "CALL NNN     - 0x2NNN\n"
    << "IFN  rX  NN  - 0x3XNN\n"
    << "IF   rX  NN  - 0x4XNN\n"
    << "IFN  rX  rY  - 0x5XY0\n"
    << "SET  rX  NN  - 0x6XNN\n"
    << "ADD  rX  NN  - 0x7XNN\n"
    << "SET  rX  rY  - 0x8XY0\n"
    << "OR   rX  rY  - 0x8XY1\n"
    << "AND  rX  rY  - 0x8XY2\n"
    << "XOR  rX  rY  - 0x8XY3\n"
    << "ADD  rX  rY  - 0x8XY4\n"
    << "SUB  rX  rY  - 0x8XY5\n"
    << "SHR  rX  rY  - 0x8XY6\n"
    << "RSUB rX  rY  - 0x8XY7\n"
    << "SHL  rX  rY  - 0x8XYE\n"
    << "IF   rX  rY  - 0x9XY0\n"
    << "IDX  NNN     - 0xANNN\n"
    << "JMP0 NNN     - 0xBNNN\n"
    << "RND  rX NN   - 0xCXNN\n"
    << "DRAW rX rY N - 0xDXYN\n"
    << "IFK  rX      - 0xEX9E\n"
    << "IFNK rX      - 0xEXA1\n"
    << "GDEL rX      - 0xFX07\n"
    << "WKEY rX      - 0xFX0A\n"
    << "SDEL rX      - 0xFX15\n"
    << "SAUD rX      - 0xFX18\n"
    << "IADD rX      - 0xFX1E\n"
    << "CHAR rX      - 0xFX29\n"
    << "SEP  rX      - 0xFX33\n"
    << "STOR rX      - 0xFX55\n"
    << "LOAD rX      - 0xFX65\n";

  return 1;
}

} // anonymous namespace

int main(int argc, char* argv[]) {
  if (argc != 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
    return help(argv[0]);
  }

  io::infile = ifstream(argv[1], ios::binary);
  if (!io::infile) {
    cerr << argv[0] << ": Unable to open " << argv[1] << "\n";
    return 1;
  }

  stringstream ss;
  ss << argv[1] << ".out";
  string const outfile_name{ss.str()};
  io::outfile = ofstream(outfile_name, ios::binary);
  if (!io::outfile) {
    cerr << argv[0] << ": Unable to open " << outfile_name << "\n";
    return 1;
  }

  map<string const, function<void()>> const op2fun {
    {"CLS",  bind(op::OP,   0x00, 0xE0) },
    {"RET",  bind(op::OP,   0x00, 0xEE) },
    {"JMP",  bind(op::NNN, "JMP", 0x10)},
    {"CALL", bind(op::NNN,"CALL", 0x20)},
    {"IFN",  bind(op::RV,  "IFN", 0x30, 0x50, 0x00)},
    {"IF",   bind(op::RV,  "IFN", 0x40, 0x90, 0x00)},
    {"SET",  bind(op::RV,  "IFN", 0x60, 0x80, 0x00)},
    {"ADD",  bind(op::RV,  "IFN", 0x70, 0x80, 0x04)},
    {"OR",   bind(op::RR,   "OR", 0x80, 0x01)},
    {"AND",  bind(op::RR,  "AND", 0x80, 0x02)},
    {"XOR",  bind(op::RR,  "XOR", 0x80, 0x03)},
    {"SUB",  bind(op::RR,  "SUB", 0x80, 0x05)},
    {"SHR",  bind(op::RR,  "SHR", 0x80, 0x06)},
    {"RSUB", bind(op::RR, "RSUB", 0x80, 0x07)},
    {"SHL",  bind(op::RR,  "SHL", 0x80, 0x0E)},
    {"IDX",  bind(op::NNN, "IDX", 0xA0)},
    {"JMP0", bind(op::NNN,"JMP0", 0xB0)},
    {"RND",  bind(op::RNN, "RND", 0xC0)},
    {"DRAW", bind(op::RRN,"DRAW", 0xD0)},
    {"IFK",  bind(op::R,   "IFK", 0xE0, 0x9E)},
    {"IFNK", bind(op::R,  "IFNK", 0xE0, 0xA1)},
    {"GDEL", bind(op::R,  "GDEL", 0xF0, 0x07)},
    {"WKEY", bind(op::R,  "WKEY", 0xF0, 0x0A)},
    {"SDEL", bind(op::R,  "SDEL", 0xF0, 0x15)},
    {"SAUD", bind(op::R,  "SAUD", 0xF0, 0x18)},
    {"IADD", bind(op::R,  "IADD", 0xF0, 0x1E)},
    {"CHAR", bind(op::R,  "CHAR", 0xF0, 0x29)},
    {"SEP",  bind(op::R,   "SEP", 0xF0, 0x33)},
    {"STOR", bind(op::R,  "STOR", 0xF0, 0x55)},
    {"LOAD", bind(op::R,  "LOAD", 0xF0, 0x65)},
  };

  for (;;) {
    // This constructor will exit when no more input is received
    string const tok{io::next_token()};

    auto const fun{op2fun.find(tok)};
    if (fun == op2fun.end()) {
      io::exit_err("Unknown command '" + tok + "'\n");
    }

    fun->second();
  }

  // Not reached
}
<commit_msg>Remove typos<commit_after>#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <functional>

using namespace std;

namespace {

namespace io {

enum token_type {
  REG,
  NN
};

ofstream outfile;
ifstream infile;

void exit_ok() {
  infile.close();
  outfile.close();
  exit(0);
}

void exit_err(string const& error) {
  cerr << error;
  infile.close();
  outfile.close();
  exit(1);
}

void write_bins(char lhs, char rhs) {
  outfile.write(static_cast<char*>(&lhs), 1);
  outfile.write(static_cast<char*>(&rhs), 1);
  if (outfile.fail()) {
    exit_err("Error writing to disk");
  }
}

int xtoi(string const& x) {
  try {
    return stoi(x, 0, 16);
  } catch (exception &e) {
    return -1;
  }
}

string next_token() {
  string value;
  io::infile >> value;
  if (!io::infile) {
    io::exit_ok();
  }
  return value;
}

void tok2n(string const& name, string&& value, char& n) {
  int target = xtoi(value);
  if (0 > target || 0xF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-F]\n");
  }
  n = target;
}

void tok2nn(string const& name, string&& value, char& nn) {
  int target = xtoi(value);
  if (0 > target || 0xFF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-FF]\n");
  }
  nn = target;
}

void tok2nnn(string const& name, string&& value, char& lhs, char& rhs) {
  int target = xtoi(value);
  if (0 > target || 0xFFF < target) {
    exit_err("Error: " + name + " needs to be supplied with a value [0-FFF]\n");
  }
  lhs = target >> 8;
  rhs = target & 0xFF;
}

void tok2reg(string const& name, string&& value, char& reg) {
  if (value.at(0) != 'r') {
    exit_err("Error: " + name + " needs to be supplied with a register r[0-F]\n");
  }

  int target = xtoi(value.substr(1));
  if (0 > target || 0xF < target) {
    exit_err("Error: " + name + " needs to be supplied with a register r[0-F]\n");
  }
  reg = target;
}

void tok2reg_or_nn(string const& name, string&& value, char& reg_or_nn, io::token_type& t) {
  if (value.at(0) == 'r') {
    t = REG;
    tok2reg(name, forward<string>(value), reg_or_nn);
  } else {
    t = NN;
    tok2nn(name, forward<string>(value), reg_or_nn);
  }
}

} // io

namespace op {

// These variables are shared between all below functions
char lhs;
char rhs;
char rhs2;
io::token_type t;

inline void OP(char lhs, char rhs) { io::write_bins(lhs, rhs); }

inline void R(string const& name, char lop, char rop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::write_bins(lop + lhs, rop);
}

inline void RR(string const& name, char lop, char rop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg(name, io::next_token(), rhs);
  io::write_bins(lop + lhs, (rhs << 4) + rop);
}

inline void NNN(string const& name, char op) {
  io::tok2nnn(name, io::next_token(), lhs, rhs);
  io::write_bins(op + lhs, rhs);
}

inline void RNN(string const& name, char lop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2nn(name, io::next_token(), rhs);
  io::write_bins(lop + lhs, rhs);
}

inline void RRN(string const& name, char lop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg(name, io::next_token(), rhs);
  io::tok2n(name, io::next_token(), rhs2);
  io::write_bins(lop + lhs, (rhs << 4) + rhs2);
}

inline void RV(string const& name, char nnop, char rlop, char rrop) {
  io::tok2reg(name, io::next_token(), lhs);
  io::tok2reg_or_nn(name, io::next_token(), rhs, t);
  if (t == io::NN)       { io::write_bins(nnop + lhs, rhs); }
  else if (t == io::REG) { io::write_bins(rlop + lhs, (rhs << 4) + rrop); }
  else                   { io::exit_err(name + ": Unknown type\n"); }
}

} // op

int help(string program_name) {
  cerr
    << "Usage: " << program_name << " FILE\n\n"
    << "Available commands\n"
    << "CLS          - 0x00E0\n"
    << "RET          - 0x00EE\n"
    << "JMP  NNN     - 0x1NNN\n"
    << "CALL NNN     - 0x2NNN\n"
    << "IFN  rX  NN  - 0x3XNN\n"
    << "IF   rX  NN  - 0x4XNN\n"
    << "IFN  rX  rY  - 0x5XY0\n"
    << "SET  rX  NN  - 0x6XNN\n"
    << "ADD  rX  NN  - 0x7XNN\n"
    << "SET  rX  rY  - 0x8XY0\n"
    << "OR   rX  rY  - 0x8XY1\n"
    << "AND  rX  rY  - 0x8XY2\n"
    << "XOR  rX  rY  - 0x8XY3\n"
    << "ADD  rX  rY  - 0x8XY4\n"
    << "SUB  rX  rY  - 0x8XY5\n"
    << "SHR  rX  rY  - 0x8XY6\n"
    << "RSUB rX  rY  - 0x8XY7\n"
    << "SHL  rX  rY  - 0x8XYE\n"
    << "IF   rX  rY  - 0x9XY0\n"
    << "IDX  NNN     - 0xANNN\n"
    << "JMP0 NNN     - 0xBNNN\n"
    << "RND  rX NN   - 0xCXNN\n"
    << "DRAW rX rY N - 0xDXYN\n"
    << "IFK  rX      - 0xEX9E\n"
    << "IFNK rX      - 0xEXA1\n"
    << "GDEL rX      - 0xFX07\n"
    << "WKEY rX      - 0xFX0A\n"
    << "SDEL rX      - 0xFX15\n"
    << "SAUD rX      - 0xFX18\n"
    << "IADD rX      - 0xFX1E\n"
    << "CHAR rX      - 0xFX29\n"
    << "SEP  rX      - 0xFX33\n"
    << "STOR rX      - 0xFX55\n"
    << "LOAD rX      - 0xFX65\n";

  return 1;
}

} // anonymous namespace

int main(int argc, char* argv[]) {
  if (argc != 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
    return help(argv[0]);
  }

  io::infile = ifstream(argv[1], ios::binary);
  if (!io::infile) {
    cerr << argv[0] << ": Unable to open " << argv[1] << "\n";
    return 1;
  }

  stringstream ss;
  ss << argv[1] << ".out";
  string const outfile_name{ss.str()};
  io::outfile = ofstream(outfile_name, ios::binary);
  if (!io::outfile) {
    cerr << argv[0] << ": Unable to open " << outfile_name << "\n";
    return 1;
  }

  map<string const, function<void()>> const op2fun {
    {"CLS",  bind(op::OP,   0x00, 0xE0) },
    {"RET",  bind(op::OP,   0x00, 0xEE) },
    {"JMP",  bind(op::NNN, "JMP", 0x10)},
    {"CALL", bind(op::NNN,"CALL", 0x20)},
    {"IFN",  bind(op::RV,  "IFN", 0x30, 0x50, 0x00)},
    {"IF",   bind(op::RV,   "IF", 0x40, 0x90, 0x00)},
    {"SET",  bind(op::RV,  "SET", 0x60, 0x80, 0x00)},
    {"ADD",  bind(op::RV,  "ADD", 0x70, 0x80, 0x04)},
    {"OR",   bind(op::RR,   "OR", 0x80, 0x01)},
    {"AND",  bind(op::RR,  "AND", 0x80, 0x02)},
    {"XOR",  bind(op::RR,  "XOR", 0x80, 0x03)},
    {"SUB",  bind(op::RR,  "SUB", 0x80, 0x05)},
    {"SHR",  bind(op::RR,  "SHR", 0x80, 0x06)},
    {"RSUB", bind(op::RR, "RSUB", 0x80, 0x07)},
    {"SHL",  bind(op::RR,  "SHL", 0x80, 0x0E)},
    {"IDX",  bind(op::NNN, "IDX", 0xA0)},
    {"JMP0", bind(op::NNN,"JMP0", 0xB0)},
    {"RND",  bind(op::RNN, "RND", 0xC0)},
    {"DRAW", bind(op::RRN,"DRAW", 0xD0)},
    {"IFK",  bind(op::R,   "IFK", 0xE0, 0x9E)},
    {"IFNK", bind(op::R,  "IFNK", 0xE0, 0xA1)},
    {"GDEL", bind(op::R,  "GDEL", 0xF0, 0x07)},
    {"WKEY", bind(op::R,  "WKEY", 0xF0, 0x0A)},
    {"SDEL", bind(op::R,  "SDEL", 0xF0, 0x15)},
    {"SAUD", bind(op::R,  "SAUD", 0xF0, 0x18)},
    {"IADD", bind(op::R,  "IADD", 0xF0, 0x1E)},
    {"CHAR", bind(op::R,  "CHAR", 0xF0, 0x29)},
    {"SEP",  bind(op::R,   "SEP", 0xF0, 0x33)},
    {"STOR", bind(op::R,  "STOR", 0xF0, 0x55)},
    {"LOAD", bind(op::R,  "LOAD", 0xF0, 0x65)},
  };

  for (;;) {
    // This constructor will exit when no more input is received
    string const tok{io::next_token()};

    auto const fun{op2fun.find(tok)};
    if (fun == op2fun.end()) {
      io::exit_err("Unknown command '" + tok + "'\n");
    }

    fun->second();
  }

  // Not reached
}
<|endoftext|>


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

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/in_process_webkit/indexed_db_context.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/testing_profile.h"
#include "chrome/test/thread_test_helper.h"
#include "chrome/test/ui_test_utils.h"

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    LOG(INFO) << "Navigating to URL and blocking.";
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        browser(), test_url, 2);
    LOG(INFO) << "Navigation done.";
    std::string result = browser()->GetSelectedTabContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          browser()->GetSelectedTabContents()->render_view_host(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DoesntHangTest) {
  SimpleTest(testUrl(FilePath(
      FILE_PATH_LITERAL("transaction_run_forever.html"))));
  ui_test_utils::CrashTab(browser()->GetSelectedTabContents());
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
  // Create test files.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath indexeddb_dir = temp_dir.path().Append(
      IndexedDBContext::kIndexedDBDirectory);
  ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir));

  FilePath::StringType file_name_1(FILE_PATH_LITERAL("http_foo_0"));
  file_name_1.append(IndexedDBContext::kIndexedDBExtension);
  FilePath::StringType file_name_2(FILE_PATH_LITERAL("chrome-extension_foo_0"));
  file_name_2.append(IndexedDBContext::kIndexedDBExtension);
  FilePath temp_file_path_1 = indexeddb_dir.Append(file_name_1);
  FilePath temp_file_path_2 = indexeddb_dir.Append(file_name_2);

  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_1, ".", 1));
  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_2, "o", 1));

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;
    WebKitContext *webkit_context = profile.GetWebKitContext();
    webkit_context->indexed_db_context()->set_data_path(indexeddb_dir);
    webkit_context->set_clear_local_state_on_exit(true);
  }
  // Make sure we wait until the destructor has run.
  scoped_refptr<ThreadTestHelper> helper(
      new ThreadTestHelper(BrowserThread::WEBKIT));
  ASSERT_TRUE(helper->Run());

  // Because we specified https for scheme to be skipped the second file
  // should survive and the first go into vanity.
  ASSERT_FALSE(file_util::PathExists(temp_file_path_1));
  ASSERT_TRUE(file_util::PathExists(temp_file_path_2));
}
<commit_msg>Disable some tests that need to be updated due to a WebKit patch that hasn't been rolled in yet.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/in_process_webkit/indexed_db_context.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/testing_profile.h"
#include "chrome/test/thread_test_helper.h"
#include "chrome/test/ui_test_utils.h"

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    LOG(INFO) << "Navigating to URL and blocking.";
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        browser(), test_url, 2);
    LOG(INFO) << "Navigation done.";
    std::string result = browser()->GetSelectedTabContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          browser()->GetSelectedTabContents()->render_view_host(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// http://code.google.com/p/chromium/issues/detail?id=70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_DoesntHangTest) {
  SimpleTest(testUrl(FilePath(
      FILE_PATH_LITERAL("transaction_run_forever.html"))));
  ui_test_utils::CrashTab(browser()->GetSelectedTabContents());
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ClearLocalState) {
  // Create test files.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath indexeddb_dir = temp_dir.path().Append(
      IndexedDBContext::kIndexedDBDirectory);
  ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir));

  FilePath::StringType file_name_1(FILE_PATH_LITERAL("http_foo_0"));
  file_name_1.append(IndexedDBContext::kIndexedDBExtension);
  FilePath::StringType file_name_2(FILE_PATH_LITERAL("chrome-extension_foo_0"));
  file_name_2.append(IndexedDBContext::kIndexedDBExtension);
  FilePath temp_file_path_1 = indexeddb_dir.Append(file_name_1);
  FilePath temp_file_path_2 = indexeddb_dir.Append(file_name_2);

  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_1, ".", 1));
  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_2, "o", 1));

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;
    WebKitContext *webkit_context = profile.GetWebKitContext();
    webkit_context->indexed_db_context()->set_data_path(indexeddb_dir);
    webkit_context->set_clear_local_state_on_exit(true);
  }
  // Make sure we wait until the destructor has run.
  scoped_refptr<ThreadTestHelper> helper(
      new ThreadTestHelper(BrowserThread::WEBKIT));
  ASSERT_TRUE(helper->Run());

  // Because we specified https for scheme to be skipped the second file
  // should survive and the first go into vanity.
  ASSERT_FALSE(file_util::PathExists(temp_file_path_1));
  ASSERT_TRUE(file_util::PathExists(temp_file_path_2));
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 <vector>

#include "chrome/browser/browser.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

// Note: WaitableEvent is not used for synchronization between the main thread
// and history backend thread because the history subsystem posts tasks back
// to the main thread. Had we tried to Signal an event in such a task
// and Wait for it on the main thread, the task would not run at all because
// the main thread would be blocked on the Wait call, resulting in a deadlock.

// A task to be scheduled on the history backend thread.
// Notifies the main thread after all history backend thread tasks have run.
class WaitForHistoryTask : public HistoryDBTask {
 public:
  WaitForHistoryTask() {
  }

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
};

// Enumerates all history contents on the backend thread.
class HistoryEnumerator : public HistoryService::URLEnumerator {
 public:
  explicit HistoryEnumerator(HistoryService* history) {
    EXPECT_TRUE(history);
    if (!history)
      return;

    ChromeThread::PostTask(
        ChromeThread::UI,
        FROM_HERE,
        NewRunnableMethod(history, &HistoryService::IterateURLs, this));
    ui_test_utils::RunMessageLoop();
  }

  virtual void OnURL(const GURL& url) {
    urls_.push_back(url);
  }

  virtual void OnComplete(bool success) {
    ChromeThread::PostTask(
        ChromeThread::UI,
        FROM_HERE,
        new MessageLoop::QuitTask());
  }

  std::vector<GURL>& urls() { return urls_; }

 private:
  std::vector<GURL> urls_;

  DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
};

class HistoryBrowserTest : public InProcessBrowserTest {
 protected:
  PrefService* GetPrefs() {
    return GetProfile()->GetPrefs();
  }

  Profile* GetProfile() {
    return browser()->GetProfile();
  }

  HistoryService* GetHistoryService() {
    return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
  }

  std::vector<GURL> GetHistoryContents() {
    HistoryEnumerator enumerator(GetHistoryService());
    return enumerator.urls();
  }

  GURL GetTestUrl() {
    return ui_test_utils::GetTestUrl(
        FilePath(FilePath::kCurrentDirectory),
        FilePath(FILE_PATH_LITERAL("title2.html")));
  }

  void WaitForHistoryBackendToRun() {
    CancelableRequestConsumerTSimple<int> request_consumer;
    scoped_refptr<HistoryDBTask> task(new WaitForHistoryTask());
    HistoryService* history = GetHistoryService();
    ChromeThread::PostTask(ChromeThread::UI,
                           FROM_HERE,
                           NewRunnableMethod(history,
                                             &HistoryService::ScheduleDBTask,
                                             task.get(),
                                             &request_consumer));
    ui_test_utils::RunMessageLoop();
  }

  void ExpectEmptyHistory() {
    std::vector<GURL> urls(GetHistoryContents());
    EXPECT_EQ(0U, urls.size());
  }
};

// Test that the browser history is saved (default setting).
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that disabling saving browser history really works.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();
}

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabledThenDisabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  ui_test_utils::WaitForHistoryToLoad(browser());

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    // No additional entries should be present in the history.
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

}  // namespace
<commit_msg>HistoryBrowserTest.SavingHistoryDisabled and SavingHistoryDisabledThenEnabled timeout / fails<commit_after>// Copyright (c) 2010 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 <vector>

#include "chrome/browser/browser.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

// Note: WaitableEvent is not used for synchronization between the main thread
// and history backend thread because the history subsystem posts tasks back
// to the main thread. Had we tried to Signal an event in such a task
// and Wait for it on the main thread, the task would not run at all because
// the main thread would be blocked on the Wait call, resulting in a deadlock.

// A task to be scheduled on the history backend thread.
// Notifies the main thread after all history backend thread tasks have run.
class WaitForHistoryTask : public HistoryDBTask {
 public:
  WaitForHistoryTask() {
  }

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
};

// Enumerates all history contents on the backend thread.
class HistoryEnumerator : public HistoryService::URLEnumerator {
 public:
  explicit HistoryEnumerator(HistoryService* history) {
    EXPECT_TRUE(history);
    if (!history)
      return;

    ChromeThread::PostTask(
        ChromeThread::UI,
        FROM_HERE,
        NewRunnableMethod(history, &HistoryService::IterateURLs, this));
    ui_test_utils::RunMessageLoop();
  }

  virtual void OnURL(const GURL& url) {
    urls_.push_back(url);
  }

  virtual void OnComplete(bool success) {
    ChromeThread::PostTask(
        ChromeThread::UI,
        FROM_HERE,
        new MessageLoop::QuitTask());
  }

  std::vector<GURL>& urls() { return urls_; }

 private:
  std::vector<GURL> urls_;

  DISALLOW_COPY_AND_ASSIGN(HistoryEnumerator);
};

class HistoryBrowserTest : public InProcessBrowserTest {
 protected:
  PrefService* GetPrefs() {
    return GetProfile()->GetPrefs();
  }

  Profile* GetProfile() {
    return browser()->GetProfile();
  }

  HistoryService* GetHistoryService() {
    return GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
  }

  std::vector<GURL> GetHistoryContents() {
    HistoryEnumerator enumerator(GetHistoryService());
    return enumerator.urls();
  }

  GURL GetTestUrl() {
    return ui_test_utils::GetTestUrl(
        FilePath(FilePath::kCurrentDirectory),
        FilePath(FILE_PATH_LITERAL("title2.html")));
  }

  void WaitForHistoryBackendToRun() {
    CancelableRequestConsumerTSimple<int> request_consumer;
    scoped_refptr<HistoryDBTask> task(new WaitForHistoryTask());
    HistoryService* history = GetHistoryService();
    ChromeThread::PostTask(ChromeThread::UI,
                           FROM_HERE,
                           NewRunnableMethod(history,
                                             &HistoryService::ScheduleDBTask,
                                             task.get(),
                                             &request_consumer));
    ui_test_utils::RunMessageLoop();
  }

  void ExpectEmptyHistory() {
    std::vector<GURL> urls(GetHistoryContents());
    EXPECT_EQ(0U, urls.size());
  }
};

// Test that the browser history is saved (default setting).
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryEnabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Times out on Vista only.  http://crbug.com/57994
#if defined(OS_WIN)
#define MAYBE_SavingHistoryDisabled DISABLED_SavingHistoryDisabled
#else
#define MAYBE_SavingHistoryDisabled SavingHistoryDisabled
#endif

// Test that disabling saving browser history really works.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, MAYBE_SavingHistoryDisabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  EXPECT_TRUE(GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_FALSE(GetProfile()->GetHistoryService(Profile::IMPLICIT_ACCESS));

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();
}

// Times out on Vista only.  http://crbug.com/57994
#if defined(OS_WIN)
#define MAYBE_SavingHistoryEnabledThenDisabled \
    DISABLED_SavingHistoryEnabledThenDisabled
#else
#define MAYBE_SavingHistoryEnabledThenDisabled SavingHistoryEnabledThenDisabled
#endif

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest,
    MAYBE_SavingHistoryEnabledThenDisabled) {
  EXPECT_FALSE(GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled));

  ui_test_utils::WaitForHistoryToLoad(browser());

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    // No additional entries should be present in the history.
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

// Test that changing the pref takes effect immediately
// when the browser is running.
IN_PROC_BROWSER_TEST_F(HistoryBrowserTest, SavingHistoryDisabledThenEnabled) {
  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, true);

  ui_test_utils::WaitForHistoryToLoad(browser());
  ExpectEmptyHistory();

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();
  ExpectEmptyHistory();

  GetPrefs()->SetBoolean(prefs::kSavingBrowserHistoryDisabled, false);

  ui_test_utils::NavigateToURL(browser(), GetTestUrl());
  WaitForHistoryBackendToRun();

  {
    std::vector<GURL> urls(GetHistoryContents());
    ASSERT_EQ(1U, urls.size());
    EXPECT_EQ(GetTestUrl().spec(), urls[0].spec());
  }
}

}  // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file defines a class that contains various method related to branding.
// It provides only default implementations of these methods. Usually to add
// specific branding, we will need to extend this class with a custom
// implementation.

#include "chrome/installer/util/browser_distribution.h"

#include "base/atomicops.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/path_service.h"
#include "base/lock.h"
#include "base/logging.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/google_chrome_distribution.h"
#include "chrome/installer/util/google_chrome_sxs_distribution.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/master_preferences.h"

#include "installer_util_strings.h"  // NOLINT

using installer::MasterPreferences;

namespace {
// The BrowserDistribution objects are never freed.
BrowserDistribution* g_browser_distribution = NULL;
BrowserDistribution* g_chrome_frame_distribution = NULL;
BrowserDistribution* g_ceee_distribution = NULL;

// Returns true if currently running in npchrome_frame.dll
bool IsChromeFrameModule() {
  FilePath module_path;
  PathService::Get(base::FILE_MODULE, &module_path);
  return FilePath::CompareEqualIgnoreCase(module_path.BaseName().value(),
                                          installer::kChromeFrameDll);
}

// Returns true if currently running in ceee_broker.exe
bool IsCeeeBrokerProcess() {
  FilePath exe_path;
  PathService::Get(base::FILE_EXE, &exe_path);
  return FilePath::CompareEqualIgnoreCase(exe_path.BaseName().value(),
                                          installer::kCeeeBrokerExe);
}

BrowserDistribution::Type GetCurrentDistributionType() {
  static BrowserDistribution::Type type =
      (MasterPreferences::ForCurrentProcess().install_chrome_frame() ||
       IsChromeFrameModule()) ?
          BrowserDistribution::CHROME_FRAME :
          BrowserDistribution::CHROME_BROWSER;
  return type;
}

}  // end namespace

BrowserDistribution::BrowserDistribution(
    const installer::MasterPreferences& prefs)
    : type_(BrowserDistribution::CHROME_BROWSER) {
}

template<class DistributionClass>
BrowserDistribution* BrowserDistribution::GetOrCreateBrowserDistribution(
    const installer::MasterPreferences& prefs,
    BrowserDistribution** dist) {
  if (!*dist) {
    DistributionClass* temp = new DistributionClass(prefs);
    if (base::subtle::NoBarrier_CompareAndSwap(
            reinterpret_cast<base::subtle::AtomicWord*>(dist), NULL,
            reinterpret_cast<base::subtle::AtomicWord>(temp)) != NULL)
      delete temp;
  }

  return *dist;
}

BrowserDistribution* BrowserDistribution::GetDistribution() {
  const installer::MasterPreferences& prefs =
      installer::MasterPreferences::ForCurrentProcess();
  return GetSpecificDistribution(GetCurrentDistributionType(), prefs);
}

// static
BrowserDistribution* BrowserDistribution::GetSpecificDistribution(
    BrowserDistribution::Type type,
    const installer::MasterPreferences& prefs) {
  BrowserDistribution* dist = NULL;

  if (type == CHROME_FRAME) {
    dist = GetOrCreateBrowserDistribution<ChromeFrameDistribution>(
        prefs, &g_chrome_frame_distribution);
  } else {
    DCHECK_EQ(CHROME_BROWSER, type);
#if defined(GOOGLE_CHROME_BUILD)
    if (InstallUtil::IsChromeSxSProcess()) {
      dist = GetOrCreateBrowserDistribution<GoogleChromeSxSDistribution>(
          prefs, &g_browser_distribution);
    } else {
      dist = GetOrCreateBrowserDistribution<GoogleChromeDistribution>(
          prefs, &g_browser_distribution);
    }
#else
    dist = GetOrCreateBrowserDistribution<BrowserDistribution>(
        prefs, &g_browser_distribution);
#endif
  }

  return dist;
}

void BrowserDistribution::DoPostUninstallOperations(
    const Version& version, const FilePath& local_data_path,
    const std::wstring& distribution_data) {
}

std::wstring BrowserDistribution::GetAppGuid() {
  return L"";
}

std::wstring BrowserDistribution::GetApplicationName() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetAppShortCutName() {
  return GetApplicationName();
}

std::wstring BrowserDistribution::GetAlternateApplicationName() {
  return L"The Internet";
}

std::wstring BrowserDistribution::GetBrowserAppId() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetInstallSubDir() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetPublisherName() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetAppDescription() {
  return L"Browse the web";
}

std::wstring BrowserDistribution::GetLongAppDescription() {
  const std::wstring& app_description =
      installer::GetLocalizedString(IDS_PRODUCT_DESCRIPTION_BASE);
  return app_description;
}

// static
int BrowserDistribution::GetInstallReturnCode(
    installer::InstallStatus status) {
  switch (status) {
    case installer::FIRST_INSTALL_SUCCESS:
    case installer::INSTALL_REPAIRED:
    case installer::NEW_VERSION_UPDATED:
    case installer::IN_USE_UPDATED:
      return 0;
    default:
      return status;
  }
}

std::string BrowserDistribution::GetSafeBrowsingName() {
  return "chromium";
}

std::wstring BrowserDistribution::GetStateKey() {
  return L"Software\\Chromium";
}

std::wstring BrowserDistribution::GetStateMediumKey() {
  return L"Software\\Chromium";
}

std::wstring BrowserDistribution::GetStatsServerURL() {
  return L"";
}

std::wstring BrowserDistribution::GetDistributionData(HKEY root_key) {
  return L"";
}

std::wstring BrowserDistribution::GetUninstallLinkName() {
  return L"Uninstall Chromium";
}

std::wstring BrowserDistribution::GetUninstallRegPath() {
  return L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Chromium";
}

std::wstring BrowserDistribution::GetVersionKey() {
  return L"Software\\Chromium";
}

bool BrowserDistribution::CanSetAsDefault() {
  return true;
}

int BrowserDistribution::GetIconIndex() {
  return 0;
}

bool BrowserDistribution::GetChromeChannel(std::wstring* channel) {
  return false;
}

void BrowserDistribution::UpdateDiffInstallStatus(bool system_install,
    bool incremental_install, installer::InstallStatus install_status) {
}

void BrowserDistribution::LaunchUserExperiment(
    installer::InstallStatus status, const Version& version,
    const installer::Product& installation, bool system_level) {
}

void BrowserDistribution::InactiveUserToastExperiment(int flavor,
    const installer::Product& installation) {
}

std::vector<FilePath> BrowserDistribution::GetKeyFiles() {
  std::vector<FilePath> key_files;
  key_files.push_back(FilePath(installer::kChromeDll));
  return key_files;
}

std::vector<FilePath> BrowserDistribution::GetComDllList() {
  return std::vector<FilePath>();
}

void BrowserDistribution::AppendUninstallCommandLineFlags(
    CommandLine* cmd_line) {
  DCHECK(cmd_line);
  cmd_line->AppendSwitch(installer::switches::kChrome);
}
<commit_msg>Fix official build.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file defines a class that contains various method related to branding.
// It provides only default implementations of these methods. Usually to add
// specific branding, we will need to extend this class with a custom
// implementation.

#include "chrome/installer/util/browser_distribution.h"

#include "base/atomicops.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/path_service.h"
#include "base/lock.h"
#include "base/logging.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/google_chrome_distribution.h"
#include "chrome/installer/util/google_chrome_sxs_distribution.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/master_preferences.h"

#include "installer_util_strings.h"  // NOLINT

using installer::MasterPreferences;

namespace {
// The BrowserDistribution objects are never freed.
BrowserDistribution* g_browser_distribution = NULL;
BrowserDistribution* g_chrome_frame_distribution = NULL;
BrowserDistribution* g_ceee_distribution = NULL;

// Returns true if currently running in npchrome_frame.dll
bool IsChromeFrameModule() {
  FilePath module_path;
  PathService::Get(base::FILE_MODULE, &module_path);
  return FilePath::CompareEqualIgnoreCase(module_path.BaseName().value(),
                                          installer::kChromeFrameDll);
}

// Returns true if currently running in ceee_broker.exe
bool IsCeeeBrokerProcess() {
  FilePath exe_path;
  PathService::Get(base::FILE_EXE, &exe_path);
  return FilePath::CompareEqualIgnoreCase(exe_path.BaseName().value(),
                                          installer::kCeeeBrokerExe);
}

BrowserDistribution::Type GetCurrentDistributionType() {
  static BrowserDistribution::Type type =
      (MasterPreferences::ForCurrentProcess().install_chrome_frame() ||
       IsChromeFrameModule()) ?
          BrowserDistribution::CHROME_FRAME :
          BrowserDistribution::CHROME_BROWSER;
  return type;
}

}  // end namespace

BrowserDistribution::BrowserDistribution(
    const installer::MasterPreferences& prefs)
    : type_(BrowserDistribution::CHROME_BROWSER) {
}

template<class DistributionClass>
BrowserDistribution* BrowserDistribution::GetOrCreateBrowserDistribution(
    const installer::MasterPreferences& prefs,
    BrowserDistribution** dist) {
  if (!*dist) {
    DistributionClass* temp = new DistributionClass(prefs);
    if (base::subtle::NoBarrier_CompareAndSwap(
            reinterpret_cast<base::subtle::AtomicWord*>(dist), NULL,
            reinterpret_cast<base::subtle::AtomicWord>(temp)) != NULL)
      delete temp;
  }

  return *dist;
}

BrowserDistribution* BrowserDistribution::GetDistribution() {
  const installer::MasterPreferences& prefs =
      installer::MasterPreferences::ForCurrentProcess();
  return GetSpecificDistribution(GetCurrentDistributionType(), prefs);
}

// static
BrowserDistribution* BrowserDistribution::GetSpecificDistribution(
    BrowserDistribution::Type type,
    const installer::MasterPreferences& prefs) {
  BrowserDistribution* dist = NULL;

  if (type == CHROME_FRAME) {
    dist = GetOrCreateBrowserDistribution<ChromeFrameDistribution>(
        prefs, &g_chrome_frame_distribution);
  } else {
    DCHECK_EQ(CHROME_BROWSER, type);
#if defined(GOOGLE_CHROME_BUILD)
    if (InstallUtil::IsChromeSxSProcess()) {
      dist = GetOrCreateBrowserDistribution<GoogleChromeSxSDistribution>(
          prefs, &g_browser_distribution);
    } else {
      dist = GetOrCreateBrowserDistribution<GoogleChromeDistribution>(
          prefs, &g_browser_distribution);
    }
#else
    dist = GetOrCreateBrowserDistribution<BrowserDistribution>(
        prefs, &g_browser_distribution);
#endif
  }

  return dist;
}

void BrowserDistribution::DoPostUninstallOperations(
    const Version& version, const FilePath& local_data_path,
    const std::wstring& distribution_data) {
}

std::wstring BrowserDistribution::GetAppGuid() {
  return L"";
}

std::wstring BrowserDistribution::GetApplicationName() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetAppShortCutName() {
  return GetApplicationName();
}

std::wstring BrowserDistribution::GetAlternateApplicationName() {
  return L"The Internet";
}

std::wstring BrowserDistribution::GetBrowserAppId() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetInstallSubDir() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetPublisherName() {
  return L"Chromium";
}

std::wstring BrowserDistribution::GetAppDescription() {
  return L"Browse the web";
}

std::wstring BrowserDistribution::GetLongAppDescription() {
  const std::wstring& app_description =
      installer::GetLocalizedString(IDS_PRODUCT_DESCRIPTION_BASE);
  return app_description;
}

// static
int BrowserDistribution::GetInstallReturnCode(
    installer::InstallStatus status) {
  switch (status) {
    case installer::FIRST_INSTALL_SUCCESS:
    case installer::INSTALL_REPAIRED:
    case installer::NEW_VERSION_UPDATED:
    case installer::IN_USE_UPDATED:
      return 0;
    default:
      return status;
  }
}

std::string BrowserDistribution::GetSafeBrowsingName() {
  return "chromium";
}

std::wstring BrowserDistribution::GetStateKey() {
  return L"Software\\Chromium";
}

std::wstring BrowserDistribution::GetStateMediumKey() {
  return L"Software\\Chromium";
}

std::wstring BrowserDistribution::GetStatsServerURL() {
  return L"";
}

std::wstring BrowserDistribution::GetDistributionData(HKEY root_key) {
  return L"";
}

std::wstring BrowserDistribution::GetUninstallLinkName() {
  return L"Uninstall Chromium";
}

std::wstring BrowserDistribution::GetUninstallRegPath() {
  return L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Chromium";
}

std::wstring BrowserDistribution::GetVersionKey() {
  return L"Software\\Chromium";
}

bool BrowserDistribution::CanSetAsDefault() {
  return true;
}

int BrowserDistribution::GetIconIndex() {
  return 0;
}

bool BrowserDistribution::GetChromeChannel(std::wstring* channel) {
  return false;
}

void BrowserDistribution::UpdateDiffInstallStatus(bool system_install,
    bool incremental_install, installer::InstallStatus install_status) {
}

void BrowserDistribution::LaunchUserExperiment(
    installer::InstallStatus status, const Version& version,
    const installer::Product& installation, bool system_level) {
}

void BrowserDistribution::InactiveUserToastExperiment(int flavor,
    const installer::Product& installation) {
}

std::vector<FilePath> BrowserDistribution::GetKeyFiles() {
  std::vector<FilePath> key_files;
  key_files.push_back(FilePath(installer::kChromeDll));
  return key_files;
}

std::vector<FilePath> BrowserDistribution::GetComDllList() {
  return std::vector<FilePath>();
}

void BrowserDistribution::AppendUninstallCommandLineFlags(
    CommandLine* cmd_line) {
  DCHECK(cmd_line);
  cmd_line->AppendSwitch(installer::switches::kChrome);
}
<|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/ui/views/constrained_window_views.h"

#include "views/widget/native_widget_views.h"

class NativeConstrainedWindowViews : public NativeConstrainedWindow,
                                     public views::NativeWidgetViews {
 public:
  explicit NativeConstrainedWindowViews(
      NativeConstrainedWindowDelegate* delegate)
      : views::NativeWidgetViews(delegate->AsNativeWidgetDelegate()),
        delegate_(delegate) {
  }

  virtual ~NativeConstrainedWindowViews() {
  }

 private:
  // Overridden from NativeConstrainedWindow:
  virtual views::NativeWidget* AsNativeWidget() OVERRIDE {
    return this;
  }

  NativeConstrainedWindowDelegate* delegate_;

  DISALLOW_COPY_AND_ASSIGN(NativeConstrainedWindowViews);
};

////////////////////////////////////////////////////////////////////////////////
// NativeConstrainedWindow, public:

// static
NativeConstrainedWindow* NativeConstrainedWindow::CreateNativeConstrainedWindow(
    NativeConstrainedWindowDelegate* delegate) {
  return new NativeConstrainedWindowViews(delegate);
}
<commit_msg>Explicitly show ConstrainedWindowViews when activated.  Views version uses TYPE_WINDOW (to get focus working, i believe) but not TYPE_CONTROL, which is is no longer visible by default as of r103330. Show when activated.<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/ui/views/constrained_window_views.h"

#include "views/widget/native_widget_views.h"

class NativeConstrainedWindowViews : public NativeConstrainedWindow,
                                     public views::NativeWidgetViews {
 public:
  explicit NativeConstrainedWindowViews(
      NativeConstrainedWindowDelegate* delegate)
      : views::NativeWidgetViews(delegate->AsNativeWidgetDelegate()),
        delegate_(delegate) {
  }

  virtual ~NativeConstrainedWindowViews() {
  }

  virtual void Activate() OVERRIDE {
    // Views version of ConstrainedWindow is not TYPE_CONTROL and not
    // visible by default. Show when it's activated.
    Show();
    views::NativeWidgetViews::Activate();
  }

 private:
  // Overridden from NativeConstrainedWindow:
  virtual views::NativeWidget* AsNativeWidget() OVERRIDE {
    return this;
  }

  NativeConstrainedWindowDelegate* delegate_;

  DISALLOW_COPY_AND_ASSIGN(NativeConstrainedWindowViews);
};

////////////////////////////////////////////////////////////////////////////////
// NativeConstrainedWindow, public:

// static
NativeConstrainedWindow* NativeConstrainedWindow::CreateNativeConstrainedWindow(
    NativeConstrainedWindowDelegate* delegate) {
  return new NativeConstrainedWindowViews(delegate);
}
<|endoftext|>