<commit_before>/*
 * Copyright (c) 2013-2014 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <iostream>

#include <boost/assign.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <pkmn/enums.hpp>
#include <pkmn/pocket.hpp>
#include <pkmn/paths.hpp>
#include <pkmn/database/queries.hpp>
#include <pkmn/types/dict.hpp>

#include "bag_impl.hpp"

namespace pkmn
{
    bag::sptr bag::make(unsigned int game)
    {
        return sptr(new bag_impl(game));
    }

    bag::sptr bag::make(std::string game)
    {
        //FRLG and HGSS are stored without spaces
        if(game != "Black 2" and game != "White 2") boost::erase_all(game, " ");
        return make(database::get_game_id(game));
    }

    bag_impl::bag_impl(unsigned int game): bag()
    {
        _game_id = game;
        _generation = database::get_generation(_game_id);
        _pockets = pkmn::dict<std::string, pocket::sptr>();

        switch(game)
        {
            case Games::RED:
            case Games::BLUE:
            case Games::YELLOW:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                break;

            case Games::GOLD:
            case Games::SILVER:
            case Games::CRYSTAL:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Balls"] = pocket::make(_game_id, "Balls", 12);
                _contents["KeyItems"] = pocket::make(_game_id, "KeyItems", 26);
                _contents["TM/HM"] = pocket::make(_game_id, "TM/HM", 99);
                break;

            case Games::RUBY:
            case Games::SAPPHIRE:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 16);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 64);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 46);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 20);
                break;

            case Games::EMERALD:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 16);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 64);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 46);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 30);
                break;

            case Games::FIRE_RED:
            case Games::LEAF_GREEN:
                _contents["Items"] = pocket::make(_game_id, "Items", 42);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 30);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 13);
                _contents["TM Case"] = pocket::make(_game_id, "TM Case", 58);
                _contents["Berry Pouch"] = pocket::make(_game_id, "Berry Pouch", 43);
                break;

            case Games::DIAMOND:
            case Games::PEARL:
            case Games::PLATINUM:
            case Games::HEART_GOLD:
            case Games::SOUL_SILVER:
                //"Infinite" space in each pocket, but 100 should do
                _contents["Items"] = pocket::make(_game_id, "Items", 100);
                _contents["Medicine"] = pocket::make(_game_id, "Medicine", 100);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 100);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 100);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 100);
                _contents["Mail"] = pocket::make(_game_id, "Mail", 100);
                _contents["Battle Items"] = pocket::make(_game_id, "Battle Items", 100);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 100);
                break;

            case Games::BLACK:
            case Games::WHITE:
            case Games::BLACK2:
            case Games::WHITE2:
            case Games::X:
            case Games::Y:
                _contents["Items"] = pocket::make(_game_id, "Items", 310);
                _contents["Medicine"] = pocket::make(_game_id, "Medicine", 48);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 109);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 64);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 83);

            default:
                break;
        }
    }

    SQLite::Database bag_impl::_db(get_database_path().c_str());

    /*
     * The underlying SQLite database can return item categories, which correspond to bag
     * pockets, but these values are only guaranteed to be accurate for Generation VI.
     * As ugly as this 2D vector is, it's the best way to determine the correct pocket for
     * an item in earlier version groups.
     *
     * The outer vector corresponds to a game's version group, and the inner vector
     * corresponds to the Generation VI item pocket ID.
     */
    std::vector<std::vector<std::string> > bag_impl::category_pockets =
        boost::assign::list_of
        (
            boost::assign::list_of //Never used
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        }
        boost::assign::list_of
        (
            boost::assign::list_of //RB
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        )
        (
            boost::assign::list_of //Yellow
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        )
        (
            boost::assign::list_of //GS
                ("Items") //Misc
                ("Items") //Medicine
                ("Balls") //Poke Balls
                ("TM/HM") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("KeyItems") //Key
        )
        (
            boost::assign::list_of //Crystal
                ("Items") //Misc
                ("Items") //Medicine
                ("Balls") //Poke Balls
                ("TM/HM") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("KeyItems") //Key
        )
        (
            boost::assign::list_of //RS
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Emerald
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //FRLG
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TM Case") //Machines
                ("Berry Pouch") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //DP
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Platinum
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //HGSS
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //BW
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Colosseum
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //XD
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //B2W2
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //XY
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
    ;

    std::string bag_impl::get_game() {return database::get_game_name(_game_id);}

    unsigned int bag_impl::get_generation() {return _generation;}

    unsigned int bag_impl::get_game_id() {return _game_id;}

    void bag_impl::add_item(pokemon_text item_name)
    {
        add_item(database::get_item_id(item_name));
    }

    void bag_impl::add_item(unsigned int item_id)
    {
        //Determine correct pocket for given item
        unsigned int version_group = database::get_version_group(_game_id);

        std::string query_string(str(boost::format("SELECT pocket_id FROM item_categories WHERE id=%d")
                                     % database::get_item_category(item_id)));
        SQLite::Statement pocket_id_query(_db, query_string.c_str());
        unsigned int pocket_id = (pocket_id_query.executeStep()) ? int(pocket_id_query.getColumn(0)) : 0;

        _pockets[category_pockets[version_group][pocket_id]].add_item(item_id);
    }

    void bag_impl::add_item(item::sptr item_sptr)
    {
        add_item(item_sptr->get_item_id());
    }

    pocket::sptr bag_impl::get_pocket(std::string name) {return _contents[name];}

    void bag_impl::get_pocket_list(std::vector<std::string> &pocket_vec) {pocket_vec = _contents.keys();}

    void bag_impl::_check() const
    {
        FOREACH(std::string& key, _contents.keys().begin(), _contents.keys().end())
        {
            if(_game_id != _contents[key]->get_game_id())
            {
                throw std::runtime_error(str(boost::format("Pocket \"%s\" is invalid!")
                                             % key));
            }
        }
    }
} /* namespace pkmn */
<commit_msg>bag: fixed Gen IV pocket sizes<commit_after>/*
 * Copyright (c) 2013-2014 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <iostream>

#include <boost/assign.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <pkmn/enums.hpp>
#include <pkmn/pocket.hpp>
#include <pkmn/paths.hpp>
#include <pkmn/database/queries.hpp>
#include <pkmn/types/dict.hpp>

#include "bag_impl.hpp"

namespace pkmn
{
    bag::sptr bag::make(unsigned int game)
    {
        return sptr(new bag_impl(game));
    }

    bag::sptr bag::make(std::string game)
    {
        //FRLG and HGSS are stored without spaces
        if(game != "Black 2" and game != "White 2") boost::erase_all(game, " ");
        return make(database::get_game_id(game));
    }

    bag_impl::bag_impl(unsigned int game): bag()
    {
        _game_id = game;
        _generation = database::get_generation(_game_id);
        _pockets = pkmn::dict<std::string, pocket::sptr>();

        switch(game)
        {
            case Games::RED:
            case Games::BLUE:
            case Games::YELLOW:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                break;

            case Games::GOLD:
            case Games::SILVER:
            case Games::CRYSTAL:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Balls"] = pocket::make(_game_id, "Balls", 12);
                _contents["KeyItems"] = pocket::make(_game_id, "KeyItems", 26);
                _contents["TM/HM"] = pocket::make(_game_id, "TM/HM", 99);
                break;

            case Games::RUBY:
            case Games::SAPPHIRE:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 16);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 64);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 46);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 20);
                break;

            case Games::EMERALD:
                _contents["Items"] = pocket::make(_game_id, "Items", 20);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 16);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 64);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 46);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 30);
                break;

            case Games::FIRE_RED:
            case Games::LEAF_GREEN:
                _contents["Items"] = pocket::make(_game_id, "Items", 42);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 30);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 13);
                _contents["TM Case"] = pocket::make(_game_id, "TM Case", 58);
                _contents["Berry Pouch"] = pocket::make(_game_id, "Berry Pouch", 43);
                break;

            case Games::DIAMOND:
            case Games::PEARL:
            case Games::PLATINUM:
                _contents["Items"] = pocket::make(_game_id, "Items", 165);
                _contents["Medicine"] = pocket::make(_game_id, "Medicine", 40);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 15);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 100);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 64);
                _contents["Mail"] = pocket::make(_game_id, "Mail", 12);
                _contents["Battle Items"] = pocket::make(_game_id, "Battle Items", 30);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 50);
                break;

            case Games::HEART_GOLD:
            case Games::SOUL_SILVER:
                _contents["Items"] = pocket::make(_game_id, "Items", 165);
                _contents["Medicine"] = pocket::make(_game_id, "Medicine", 40);
                _contents["Poke Balls"] = pocket::make(_game_id, "Poke Balls", 24);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 100);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 64);
                _contents["Mail"] = pocket::make(_game_id, "Mail", 12);
                _contents["Battle Items"] = pocket::make(_game_id, "Battle Items", 30);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 43);
                break;

            case Games::BLACK:
            case Games::WHITE:
            case Games::BLACK2:
            case Games::WHITE2:
            case Games::X:
            case Games::Y:
                _contents["Items"] = pocket::make(_game_id, "Items", 310);
                _contents["Medicine"] = pocket::make(_game_id, "Medicine", 48);
                _contents["TMs and HMs"] = pocket::make(_game_id, "TMs and HMs", 109);
                _contents["Berries"] = pocket::make(_game_id, "Berries", 64);
                _contents["Key Items"] = pocket::make(_game_id, "Key Items", 83);

            default:
                break;
        }
    }

    SQLite::Database bag_impl::_db(get_database_path().c_str());

    /*
     * The underlying SQLite database can return item categories, which correspond to bag
     * pockets, but these values are only guaranteed to be accurate for Generation VI.
     * As ugly as this 2D vector is, it's the best way to determine the correct pocket for
     * an item in earlier version groups.
     *
     * The outer vector corresponds to a game's version group, and the inner vector
     * corresponds to the Generation VI item pocket ID.
     */
    std::vector<std::vector<std::string> > bag_impl::category_pockets =
        boost::assign::list_of
        (
            boost::assign::list_of //Never used
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        }
        boost::assign::list_of
        (
            boost::assign::list_of //RB
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        )
        (
            boost::assign::list_of //Yellow
                ("Items") //Misc
                ("Items") //Medicine
                ("Items") //Poke Balls
                ("Items") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Items") //Key
        )
        (
            boost::assign::list_of //GS
                ("Items") //Misc
                ("Items") //Medicine
                ("Balls") //Poke Balls
                ("TM/HM") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("KeyItems") //Key
        )
        (
            boost::assign::list_of //Crystal
                ("Items") //Misc
                ("Items") //Medicine
                ("Balls") //Poke Balls
                ("TM/HM") //Machines
                ("Items") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("KeyItems") //Key
        )
        (
            boost::assign::list_of //RS
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Emerald
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //FRLG
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TM Case") //Machines
                ("Berry Pouch") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //DP
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Platinum
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //HGSS
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Mail") //Mail
                ("Battle Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //BW
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //Colosseum
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //XD
                ("Items") //Misc
                ("Items") //Medicine
                ("Poke Balls") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //B2W2
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
        (
            boost::assign::list_of //XY
                ("Items") //Misc
                ("Medicine") //Medicine
                ("Items") //Poke Balls
                ("TMs and HMs") //Machines
                ("Berries") //Berries
                ("Items") //Mail
                ("Items") //Battle
                ("Key Items") //Key
        )
    ;

    std::string bag_impl::get_game() {return database::get_game_name(_game_id);}

    unsigned int bag_impl::get_generation() {return _generation;}

    unsigned int bag_impl::get_game_id() {return _game_id;}

    void bag_impl::add_item(pokemon_text item_name)
    {
        add_item(database::get_item_id(item_name));
    }

    void bag_impl::add_item(unsigned int item_id)
    {
        //Determine correct pocket for given item
        unsigned int version_group = database::get_version_group(_game_id);

        std::string query_string(str(boost::format("SELECT pocket_id FROM item_categories WHERE id=%d")
                                     % database::get_item_category(item_id)));
        SQLite::Statement pocket_id_query(_db, query_string.c_str());
        unsigned int pocket_id = (pocket_id_query.executeStep()) ? int(pocket_id_query.getColumn(0)) : 0;

        _pockets[category_pockets[version_group][pocket_id]].add_item(item_id);
    }

    void bag_impl::add_item(item::sptr item_sptr)
    {
        add_item(item_sptr->get_item_id());
    }

    pocket::sptr bag_impl::get_pocket(std::string name) {return _contents[name];}

    void bag_impl::get_pocket_list(std::vector<std::string> &pocket_vec) {pocket_vec = _contents.keys();}

    void bag_impl::_check() const
    {
        FOREACH(std::string& key, _contents.keys().begin(), _contents.keys().end())
        {
            if(_game_id != _contents[key]->get_game_id())
            {
                throw std::runtime_error(str(boost::format("Pocket \"%s\" is invalid!")
                                             % key));
            }
        }
    }
} /* namespace pkmn */
<|endoftext|>


<commit_before>#include "installercontroller.h"

#include <QProcess>
#include <QtTest>

static const QString configFile = SRCDIR + QStringLiteral("../../../installer/config/config.xml");
static const QString configScript = SRCDIR + QStringLiteral("../../../installer/config/controller.qs");
static const QString pkgFile = SRCDIR + QStringLiteral("../../../installer/packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta/package.xml");
static const QString binarycreator = BINDIR + QStringLiteral("binarycreator");
static const QString repogen = BINDIR + QStringLiteral("repogen");

InstallerController::InstallerController(QObject *parent) :
	QObject(parent),
	_version(1, 0, 0),
	_buildDir()
{
	setVersion(_version);
}

void InstallerController::createRepository()
{
	qDebug() << "Creating repository";
	auto res = QProcess::execute(repogen, {"--update-new-components", "-p", _buildDir.path() + "/packages", _buildDir.path() + "/repository"});
	QCOMPARE(res, 0);
}

void InstallerController::createInstaller()
{
	qDebug() << "Creating installer";
	QFile configSrc(configFile);
	QFile configOut(_buildDir.path() + "/config.xml");

	QVERIFY(configSrc.open(QIODevice::ReadOnly | QIODevice::Text));
	QVERIFY(configOut.open(QIODevice::WriteOnly | QIODevice::Text));
	auto src = QString::fromUtf8(configSrc.readAll());
	configOut.write(src
					.arg(_buildDir.path() + "/install")
					.arg(_buildDir.path())
					.toUtf8());
	configSrc.close();
	configOut.close();

	auto res = QProcess::execute(binarycreator, {"-n", "-c", configOut.fileName(), "-p", _buildDir.path() + "/packages", _buildDir.path() + "/QtAutoUpdaterTestInstaller"});
	QCOMPARE(res, 0);
}

QString toSystemExe(QString basePath)
{
#if defined(Q_OS_WIN32)
	if(!basePath.endsWith(QStringLiteral(".exe")))
		return basePath + QStringLiteral(".exe");
	else
		return basePath;
#elif defined(Q_OS_OSX)
	if(basePath.endsWith(QStringLiteral(".app")))
		basePath.truncate(basePath.lastIndexOf(QStringLiteral(".")));
	return basePath + QStringLiteral(".app/Contents/MacOS/") + QFileInfo(basePath).fileName();
#elif defined(Q_OS_UNIX)
	return basePath;
#endif
}

void InstallerController::installLocal()
{
	qDebug() << "Installing example";
	QVERIFY(QFile::exists(toSystemExe(_buildDir.path() + "/QtAutoUpdaterTestInstaller")));
	auto res = QProcess::execute(toSystemExe(_buildDir.path() + "/QtAutoUpdaterTestInstaller"), {"--script", configScript, "--verbose"});
	QCOMPARE(res, 0);
}

void InstallerController::runUpdater()
{
	qDebug() << "Running updater";
}

QVersionNumber InstallerController::version() const
{
	return _version;
}

QString InstallerController::maintenanceToolPath() const
{
	return _buildDir.path() + "/install";
}

void InstallerController::setVersion(QVersionNumber version)
{
	qDebug() << "Updating repository version";
	_version = version;

	QDir tDir(_buildDir.path());
	QVERIFY(tDir.mkpath("packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta"));
	QVERIFY(tDir.mkpath("packages/de.skycoder42.QtAutoUpdaterTestInstaller/data"));

	QFile pkgSrc(pkgFile);
	QFile pkgOut(_buildDir.path() + "/packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta/package.xml");

	QVERIFY(pkgSrc.open(QIODevice::ReadOnly | QIODevice::Text));
	QVERIFY(pkgOut.open(QIODevice::WriteOnly | QIODevice::Text));
	auto src = QString::fromUtf8(pkgSrc.readAll());
	pkgOut.write(src.arg(_version.toString()).toUtf8());
	pkgSrc.close();
	pkgOut.close();

	QFile dataFile(_buildDir.path() + "/packages/de.skycoder42.QtAutoUpdaterTestInstaller/data/version.txt");
	QVERIFY(dataFile.open(QIODevice::WriteOnly | QIODevice::Text));
	dataFile.write(_version.toString().toUtf8());
	dataFile.close();
}
<commit_msg>try with explicit platform<commit_after>#include "installercontroller.h"

#include <QProcess>
#include <QtTest>

static const QString configFile = SRCDIR + QStringLiteral("../../../installer/config/config.xml");
static const QString configScript = SRCDIR + QStringLiteral("../../../installer/config/controller.qs");
static const QString pkgFile = SRCDIR + QStringLiteral("../../../installer/packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta/package.xml");
static const QString binarycreator = BINDIR + QStringLiteral("binarycreator");
static const QString repogen = BINDIR + QStringLiteral("repogen");

InstallerController::InstallerController(QObject *parent) :
	QObject(parent),
	_version(1, 0, 0),
	_buildDir()
{
	setVersion(_version);
}

void InstallerController::createRepository()
{
	qDebug() << "Creating repository";
	auto res = QProcess::execute(repogen, {"--update-new-components", "-p", _buildDir.path() + "/packages", _buildDir.path() + "/repository"});
	QCOMPARE(res, 0);
}

void InstallerController::createInstaller()
{
	qDebug() << "Creating installer";
	QFile configSrc(configFile);
	QFile configOut(_buildDir.path() + "/config.xml");

	QVERIFY(configSrc.open(QIODevice::ReadOnly | QIODevice::Text));
	QVERIFY(configOut.open(QIODevice::WriteOnly | QIODevice::Text));
	auto src = QString::fromUtf8(configSrc.readAll());
	configOut.write(src
					.arg(_buildDir.path() + "/install")
					.arg(_buildDir.path())
					.toUtf8());
	configSrc.close();
	configOut.close();

	auto res = QProcess::execute(binarycreator, {"-n", "-c", configOut.fileName(), "-p", _buildDir.path() + "/packages", _buildDir.path() + "/QtAutoUpdaterTestInstaller"});
	QCOMPARE(res, 0);
}

QString toSystemExe(QString basePath)
{
#if defined(Q_OS_WIN32)
	if(!basePath.endsWith(QStringLiteral(".exe")))
		return basePath + QStringLiteral(".exe");
	else
		return basePath;
#elif defined(Q_OS_OSX)
	if(basePath.endsWith(QStringLiteral(".app")))
		basePath.truncate(basePath.lastIndexOf(QStringLiteral(".")));
	return basePath + QStringLiteral(".app/Contents/MacOS/") + QFileInfo(basePath).fileName();
#elif defined(Q_OS_UNIX)
	return basePath;
#endif
}

void InstallerController::installLocal()
{
	qDebug() << "Installing example";
	QVERIFY(QFile::exists(toSystemExe(_buildDir.path() + "/QtAutoUpdaterTestInstaller")));
#if defined(Q_OS_WIN32)
	auto res = QProcess::execute(toSystemExe(_buildDir.path() + "/QtAutoUpdaterTestInstaller"), {"-platform", "windows", "--script", configScript, "--verbose"});
#else
	auto res = QProcess::execute(toSystemExe(_buildDir.path() + "/QtAutoUpdaterTestInstaller"), {"--script", configScript, "--verbose"});
#endif
	QCOMPARE(res, 0);
}

void InstallerController::runUpdater()
{
	qDebug() << "Running updater";
}

QVersionNumber InstallerController::version() const
{
	return _version;
}

QString InstallerController::maintenanceToolPath() const
{
	return _buildDir.path() + "/install";
}

void InstallerController::setVersion(QVersionNumber version)
{
	qDebug() << "Updating repository version";
	_version = version;

	QDir tDir(_buildDir.path());
	QVERIFY(tDir.mkpath("packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta"));
	QVERIFY(tDir.mkpath("packages/de.skycoder42.QtAutoUpdaterTestInstaller/data"));

	QFile pkgSrc(pkgFile);
	QFile pkgOut(_buildDir.path() + "/packages/de.skycoder42.QtAutoUpdaterTestInstaller/meta/package.xml");

	QVERIFY(pkgSrc.open(QIODevice::ReadOnly | QIODevice::Text));
	QVERIFY(pkgOut.open(QIODevice::WriteOnly | QIODevice::Text));
	auto src = QString::fromUtf8(pkgSrc.readAll());
	pkgOut.write(src.arg(_version.toString()).toUtf8());
	pkgSrc.close();
	pkgOut.close();

	QFile dataFile(_buildDir.path() + "/packages/de.skycoder42.QtAutoUpdaterTestInstaller/data/version.txt");
	QVERIFY(dataFile.open(QIODevice::WriteOnly | QIODevice::Text));
	dataFile.write(_version.toString().toUtf8());
	dataFile.close();
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOpenGLCamera.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkOpenGLCamera.h"

#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOutputWindow.h"
#include "vtkRenderWindow.h"
#include "vtkgluPickMatrix.h"

#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

#include <math.h>

#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLCamera, "1.54");
vtkStandardNewMacro(vtkOpenGLCamera);
#endif

#define vtkOpenGLCameraBound(vpu, vpv) \
{ \
  if (vpu > 1.0) \
    { \
    vpu = 1.0; \
    } \
  if (vpu < 0.0) \
    { \
    vpu = 0.0; \
    } \
  if (vpv > 1.0) \
    { \
    vpv = 1.0; \
    } \
  if (vpv < 0.0) \
    { \
    vpv = 0.0; \
    }  \
}

// Implement base class method.
void vtkOpenGLCamera::Render(vtkRenderer *ren)
{
  float aspect[2];
  float *vport;
  int  lowerLeft[2];
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();

  // find out if we should stereo render
  this->Stereo = (ren->GetRenderWindow())->GetStereoRender();
  vport = ren->GetViewport();

  float *tileViewPort = ren->GetVTKWindow()->GetTileViewport();
  //int scale =
  ren->GetVTKWindow()->GetTileScale();

  float vpu, vpv;
  vpu = (vport[0] - tileViewPort[0]);
  vpv = (vport[1] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu,vpv);
  ren->NormalizedDisplayToDisplay(vpu,vpv);
  lowerLeft[0] = (int)(vpu+0.5);
  lowerLeft[1] = (int)(vpv+0.5);
  float vpu2, vpv2;
  vpu2 = (vport[2] - tileViewPort[0]);
  vpv2 = (vport[3] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu2,vpv2);
  if (vpu2 > tileViewPort[2])
    {
    vpu2 = tileViewPort[2];
    }
  if (vpv2 > tileViewPort[3])
    {
    vpv2 = tileViewPort[3];
    }
  ren->NormalizedDisplayToDisplay(vpu2,vpv2);
  int usize = (int)(vpu2 + 0.5) - lowerLeft[0];
  int vsize = (int)(vpv2 + 0.5) - lowerLeft[1];
  if (usize < 0)
    {
    usize = 0;
    }
  if (vsize < 0)
    {
    vsize = 0;
    }

  // if were on a stereo renderer draw to special parts of screen
  if (this->Stereo)
    {
    switch ((ren->GetRenderWindow())->GetStereoType())
      {
      case VTK_STEREO_CRYSTAL_EYES:
        if (this->LeftEye)
          {
          glDrawBuffer(GL_BACK_LEFT);
          }
        else
          {
          glDrawBuffer(GL_BACK_RIGHT);
          }
        break;
      case VTK_STEREO_LEFT:
        this->LeftEye = 1;
        break;
      case VTK_STEREO_RIGHT:
        this->LeftEye = 0;
        break;
      default:
        break;
      }
    }
  else
    {
    if (ren->GetRenderWindow()->GetDoubleBuffer())
      {
      glDrawBuffer(GL_BACK);
      }
    else
      {
      glDrawBuffer(GL_FRONT);
      }
    }

  glViewport(lowerLeft[0],lowerLeft[1], usize, vsize);
  glEnable( GL_SCISSOR_TEST );
  glScissor(lowerLeft[0],lowerLeft[1], usize, vsize);

  ren->ComputeAspect();
  ren->GetAspect(aspect);

  glMatrixMode( GL_PROJECTION);
  if(usize && vsize)
    {
    matrix->DeepCopy(this->GetPerspectiveTransformMatrix(1.0*usize/vsize,
                                                         -1,1));
    matrix->Transpose();
    }
  if(ren->GetIsPicking())
    {
    int size[2]; size[0] = usize; size[1] = vsize;
    glLoadIdentity();
    vtkgluPickMatrix(ren->GetPickX(), ren->GetPickY(), 1, 1, lowerLeft, size);
    glMultMatrixd(matrix->Element[0]);
    }
  else
    {
    // insert camera view transformation
    glLoadMatrixd(matrix->Element[0]);
    }

  // push the model view matrix onto the stack, make sure we
  // adjust the mode first
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();

  matrix->DeepCopy(this->GetViewTransformMatrix());
  matrix->Transpose();

  // insert camera view transformation
  glMultMatrixd(matrix->Element[0]);

  if ((ren->GetRenderWindow())->GetErase())
    {
    ren->Clear();
    }

  // if we have a stereo renderer, draw other eye next time
  if (this->Stereo)
    {
    if (this->LeftEye)
      {
      this->LeftEye = 0;
      }
    else
      {
      this->LeftEye = 1;
      }
    }

  matrix->Delete();
}

void vtkOpenGLCamera::UpdateViewport(vtkRenderer *ren)
{
  float *vport;
  int  lowerLeft[2];

  vport = ren->GetViewport();

  float *tileViewPort = ren->GetVTKWindow()->GetTileViewport();
  //int scale =
  ren->GetVTKWindow()->GetTileScale();

  float vpu, vpv;
  vpu = (vport[0] - tileViewPort[0]);
  vpv = (vport[1] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu,vpv);
  ren->NormalizedDisplayToDisplay(vpu,vpv);
  lowerLeft[0] = (int)(vpu+0.5);
  lowerLeft[1] = (int)(vpv+0.5);
  float vpu2, vpv2;
  vpu2 = (vport[2] - tileViewPort[0]);
  vpv2 = (vport[3] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu2,vpv2);
  if (vpu2 > tileViewPort[2])
    {
    vpu2 = tileViewPort[2];
    }
  if (vpv2 > tileViewPort[3])
    {
    vpv2 = tileViewPort[3];
    }
  ren->NormalizedDisplayToDisplay(vpu2,vpv2);
  int usize = (int)(vpu2 + 0.5) - lowerLeft[0];
  int vsize = (int)(vpv2 + 0.5) - lowerLeft[1];
  if (usize < 0)
    {
    usize = 0;
    }
  if (vsize < 0)
    {
    vsize = 0;
    }

  glViewport(lowerLeft[0],lowerLeft[1], usize, vsize);
  glEnable( GL_SCISSOR_TEST );
  glScissor(lowerLeft[0],lowerLeft[1], usize, vsize);
}

//----------------------------------------------------------------------------
void vtkOpenGLCamera::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>updted to consider renderers aspect ratio<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOpenGLCamera.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkOpenGLCamera.h"

#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOutputWindow.h"
#include "vtkRenderWindow.h"
#include "vtkgluPickMatrix.h"

#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

#include <math.h>

#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLCamera, "1.55");
vtkStandardNewMacro(vtkOpenGLCamera);
#endif

#define vtkOpenGLCameraBound(vpu, vpv) \
{ \
  if (vpu > 1.0) \
    { \
    vpu = 1.0; \
    } \
  if (vpu < 0.0) \
    { \
    vpu = 0.0; \
    } \
  if (vpv > 1.0) \
    { \
    vpv = 1.0; \
    } \
  if (vpv < 0.0) \
    { \
    vpv = 0.0; \
    }  \
}

// Implement base class method.
void vtkOpenGLCamera::Render(vtkRenderer *ren)
{
  float aspect[2];
  float *vport;
  int  lowerLeft[2];
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();

  // find out if we should stereo render
  this->Stereo = (ren->GetRenderWindow())->GetStereoRender();
  vport = ren->GetViewport();

  float *tileViewPort = ren->GetVTKWindow()->GetTileViewport();
  //int scale =
  ren->GetVTKWindow()->GetTileScale();

  float vpu, vpv;
  // find the lower left corner of the viewport, taking into account the
  // lower left boundary of this tile
  vpu = (vport[0] - tileViewPort[0]);
  vpv = (vport[1] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu,vpv);
  // store the result as a pixel value
  ren->NormalizedDisplayToDisplay(vpu,vpv);
  lowerLeft[0] = (int)(vpu+0.5);
  lowerLeft[1] = (int)(vpv+0.5);
  float vpu2, vpv2;
  // find the upper right corner of the viewport, taking into account the
  // lower left boundary of this tile
  vpu2 = (vport[2] - tileViewPort[0]);
  vpv2 = (vport[3] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu2,vpv2);
  // also watch for the upper right boundary of the tile
  if (vpu2 > tileViewPort[2])
    {
    vpu2 = tileViewPort[2];
    }
  if (vpv2 > tileViewPort[3])
    {
    vpv2 = tileViewPort[3];
    }
  ren->NormalizedDisplayToDisplay(vpu2,vpv2);
  // now compute the size of the intersection of the viewport with the
  // current tile
  int usize = (int)(vpu2 + 0.5) - lowerLeft[0];
  int vsize = (int)(vpv2 + 0.5) - lowerLeft[1];
  if (usize < 0)
    {
    usize = 0;
    }
  if (vsize < 0)
    {
    vsize = 0;
    }

  // if were on a stereo renderer draw to special parts of screen
  if (this->Stereo)
    {
    switch ((ren->GetRenderWindow())->GetStereoType())
      {
      case VTK_STEREO_CRYSTAL_EYES:
        if (this->LeftEye)
          {
          glDrawBuffer(GL_BACK_LEFT);
          }
        else
          {
          glDrawBuffer(GL_BACK_RIGHT);
          }
        break;
      case VTK_STEREO_LEFT:
        this->LeftEye = 1;
        break;
      case VTK_STEREO_RIGHT:
        this->LeftEye = 0;
        break;
      default:
        break;
      }
    }
  else
    {
    if (ren->GetRenderWindow()->GetDoubleBuffer())
      {
      glDrawBuffer(GL_BACK);
      }
    else
      {
      glDrawBuffer(GL_FRONT);
      }
    }

  glViewport(lowerLeft[0],lowerLeft[1], usize, vsize);
  glEnable( GL_SCISSOR_TEST );
  glScissor(lowerLeft[0],lowerLeft[1], usize, vsize);

  // some renderer subclasses may have more complicated computations for the
  // aspect ratio. SO take that into account by computing the difference
  // between our simple aspect ratio and what the actual renderer is
  // reporting.
  ren->ComputeAspect();
  ren->GetAspect(aspect);
  float aspect2[2];
  ren->vtkViewport::ComputeAspect();
  ren->vtkViewport::GetAspect(aspect2);
  float aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]);

  glMatrixMode( GL_PROJECTION);
  if(usize && vsize)
    {
    matrix->DeepCopy(this->GetPerspectiveTransformMatrix(
                       aspectModification*usize/vsize, -1,1));
    matrix->Transpose();
    }
  if(ren->GetIsPicking())
    {
    int size[2]; size[0] = usize; size[1] = vsize;
    glLoadIdentity();
    vtkgluPickMatrix(ren->GetPickX(), ren->GetPickY(), 1, 1, lowerLeft, size);
    glMultMatrixd(matrix->Element[0]);
    }
  else
    {
    // insert camera view transformation
    glLoadMatrixd(matrix->Element[0]);
    }

  // push the model view matrix onto the stack, make sure we
  // adjust the mode first
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();

  matrix->DeepCopy(this->GetViewTransformMatrix());
  matrix->Transpose();

  // insert camera view transformation
  glMultMatrixd(matrix->Element[0]);

  if ((ren->GetRenderWindow())->GetErase())
    {
    ren->Clear();
    }

  // if we have a stereo renderer, draw other eye next time
  if (this->Stereo)
    {
    if (this->LeftEye)
      {
      this->LeftEye = 0;
      }
    else
      {
      this->LeftEye = 1;
      }
    }

  matrix->Delete();
}

void vtkOpenGLCamera::UpdateViewport(vtkRenderer *ren)
{
  float *vport;
  int  lowerLeft[2];

  vport = ren->GetViewport();

  float *tileViewPort = ren->GetVTKWindow()->GetTileViewport();
  //int scale =
  ren->GetVTKWindow()->GetTileScale();

  float vpu, vpv;
  vpu = (vport[0] - tileViewPort[0]);
  vpv = (vport[1] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu,vpv);
  ren->NormalizedDisplayToDisplay(vpu,vpv);
  lowerLeft[0] = (int)(vpu+0.5);
  lowerLeft[1] = (int)(vpv+0.5);
  float vpu2, vpv2;
  vpu2 = (vport[2] - tileViewPort[0]);
  vpv2 = (vport[3] - tileViewPort[1]);
  vtkOpenGLCameraBound(vpu2,vpv2);
  if (vpu2 > tileViewPort[2])
    {
    vpu2 = tileViewPort[2];
    }
  if (vpv2 > tileViewPort[3])
    {
    vpv2 = tileViewPort[3];
    }
  ren->NormalizedDisplayToDisplay(vpu2,vpv2);
  int usize = (int)(vpu2 + 0.5) - lowerLeft[0];
  int vsize = (int)(vpv2 + 0.5) - lowerLeft[1];
  if (usize < 0)
    {
    usize = 0;
    }
  if (vsize < 0)
    {
    vsize = 0;
    }

  glViewport(lowerLeft[0],lowerLeft[1], usize, vsize);
  glEnable( GL_SCISSOR_TEST );
  glScissor(lowerLeft[0],lowerLeft[1], usize, vsize);
}

//----------------------------------------------------------------------------
void vtkOpenGLCamera::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>


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

#include "chrome/browser/ui/views/select_file_dialog_extension.h"

#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/test/test_utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/selected_file_info.h"

using content::BrowserContext;

// Mock listener used by test below.
class MockSelectFileDialogListener : public ui::SelectFileDialog::Listener {
 public:
  MockSelectFileDialogListener()
    : file_selected_(false),
      canceled_(false),
      params_(NULL) {
  }

  bool file_selected() const { return file_selected_; }
  bool canceled() const { return canceled_; }
  base::FilePath path() const { return path_; }
  void* params() const { return params_; }

  // ui::SelectFileDialog::Listener implementation.
  virtual void FileSelected(const base::FilePath& path,
                            int index,
                            void* params) override {
    file_selected_ = true;
    path_ = path;
    params_ = params;
  }
  virtual void FileSelectedWithExtraInfo(
      const ui::SelectedFileInfo& selected_file_info,
      int index,
      void* params) override {
    FileSelected(selected_file_info.local_path, index, params);
  }
  virtual void MultiFilesSelected(
      const std::vector<base::FilePath>& files, void* params) override {}
  virtual void FileSelectionCanceled(void* params) override {
    canceled_ = true;
    params_ = params;
  }

 private:
  bool file_selected_;
  bool canceled_;
  base::FilePath path_;
  void* params_;

  DISALLOW_COPY_AND_ASSIGN(MockSelectFileDialogListener);
};

class SelectFileDialogExtensionBrowserTest : public ExtensionBrowserTest {
 public:
  enum DialogButtonType {
    DIALOG_BTN_OK,
    DIALOG_BTN_CANCEL
  };

  virtual void SetUp() override {
    extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();

    // Create the dialog wrapper object, but don't show it yet.
    listener_.reset(new MockSelectFileDialogListener());
    dialog_ = new SelectFileDialogExtension(listener_.get(), NULL);

    // We have to provide at least one mount point.
    // File manager looks for "Downloads" mount point, so use this name.
    base::FilePath tmp_path;
    PathService::Get(base::DIR_TEMP, &tmp_path);
    ASSERT_TRUE(tmp_dir_.CreateUniqueTempDirUnderPath(tmp_path));
    downloads_dir_ = tmp_dir_.path().Append("Downloads");
    base::CreateDirectory(downloads_dir_);

    // Must run after our setup because it actually runs the test.
    ExtensionBrowserTest::SetUp();
  }

  virtual void TearDown() override {
    ExtensionBrowserTest::TearDown();

    // Delete the dialog first, as it holds a pointer to the listener.
    dialog_ = NULL;
    listener_.reset();

    second_dialog_ = NULL;
    second_listener_.reset();
  }

  // Creates a file system mount point for a directory.
  void AddMountPoint(const base::FilePath& path) {
    EXPECT_TRUE(file_manager::VolumeManager::Get(
        browser()->profile())->RegisterDownloadsDirectoryForTesting(path));
    browser()->profile()->GetPrefs()->SetFilePath(
        prefs::kDownloadDefaultDirectory, downloads_dir_);
  }

  void CheckJavascriptErrors() {
    content::RenderFrameHost* host =
        dialog_->GetRenderViewHost()->GetMainFrame();
    scoped_ptr<base::Value> value =
        content::ExecuteScriptAndGetValue(host, "window.JSErrorCount");
    int js_error_count = 0;
    ASSERT_TRUE(value->GetAsInteger(&js_error_count));
    ASSERT_EQ(0, js_error_count);
  }

  void OpenDialog(ui::SelectFileDialog::Type dialog_type,
                  const base::FilePath& file_path,
                  const gfx::NativeWindow& owning_window,
                  const std::string& additional_message) {
    // Spawn a dialog to open a file.  The dialog will signal that it is ready
    // via chrome.test.sendMessage() in the extension JavaScript.
    ExtensionTestMessageListener init_listener("worker-initialized",
                                               false /* will_reply */);

    scoped_ptr<ExtensionTestMessageListener> additional_listener;
    if (!additional_message.empty()) {
      additional_listener.reset(
          new ExtensionTestMessageListener(additional_message, false));
    }

    dialog_->SelectFile(dialog_type,
                        base::string16() /* title */,
                        file_path,
                        NULL /* file_types */,
                         0 /* file_type_index */,
                        FILE_PATH_LITERAL("") /* default_extension */,
                        owning_window,
                        this /* params */);

    LOG(INFO) << "Waiting for JavaScript ready message.";
    ASSERT_TRUE(init_listener.WaitUntilSatisfied());

    if (additional_listener.get()) {
      LOG(INFO) << "Waiting for JavaScript " << additional_message
                << " message.";
      ASSERT_TRUE(additional_listener->WaitUntilSatisfied());
    }

    // Dialog should be running now.
    ASSERT_TRUE(dialog_->IsRunning(owning_window));

    ASSERT_NO_FATAL_FAILURE(CheckJavascriptErrors());
  }

  void TryOpeningSecondDialog(const gfx::NativeWindow& owning_window) {
    second_listener_.reset(new MockSelectFileDialogListener());
    second_dialog_ = new SelectFileDialogExtension(second_listener_.get(),
                                                   NULL);

    // At the moment we don't really care about dialog type, but we have to put
    // some dialog type.
    second_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
                               base::string16() /* title */,
                               base::FilePath() /* default_path */,
                               NULL /* file_types */,
                               0 /* file_type_index */,
                               FILE_PATH_LITERAL("") /* default_extension */,
                               owning_window,
                               this /* params */);
  }

  void CloseDialog(DialogButtonType button_type,
                   const gfx::NativeWindow& owning_window) {
    // Inject JavaScript to click the cancel button and wait for notification
    // that the window has closed.
    content::WindowedNotificationObserver host_destroyed(
        content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
        content::NotificationService::AllSources());
    content::RenderViewHost* host = dialog_->GetRenderViewHost();
    std::string button_class =
        (button_type == DIALOG_BTN_OK) ? ".button-panel .ok" :
                                         ".button-panel .cancel";
    base::string16 script = base::ASCIIToUTF16(
        "console.log(\'Test JavaScript injected.\');"
        "document.querySelector(\'" + button_class + "\').click();");
    // The file selection handler closes the dialog and does not return control
    // to JavaScript, so do not wait for return values.
    host->GetMainFrame()->ExecuteJavaScript(script);
    LOG(INFO) << "Waiting for window close notification.";
    host_destroyed.Wait();

    // Dialog no longer believes it is running.
    ASSERT_FALSE(dialog_->IsRunning(owning_window));
  }

  scoped_ptr<MockSelectFileDialogListener> listener_;
  scoped_refptr<SelectFileDialogExtension> dialog_;

  scoped_ptr<MockSelectFileDialogListener> second_listener_;
  scoped_refptr<SelectFileDialogExtension> second_dialog_;

  base::ScopedTempDir tmp_dir_;
  base::FilePath downloads_dir_;
};

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest, CreateAndDestroy) {
  // Browser window must be up for us to test dialog window parent.
  gfx::NativeWindow native_window = browser()->window()->GetNativeWindow();
  ASSERT_TRUE(native_window != NULL);

  // Before we call SelectFile, dialog is not running/visible.
  ASSERT_FALSE(dialog_->IsRunning(native_window));
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest, DestroyListener) {
  // Some users of SelectFileDialog destroy their listener before cleaning
  // up the dialog.  Make sure we don't crash.
  dialog_->ListenerDestroyed();
  listener_.reset();
}

// TODO(jamescook): Add a test for selecting a file for an <input type='file'/>
// page element, as that uses different memory management pathways.
// crbug.com/98791

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndCancel) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // base::FilePath() for default path.
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  // Press cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndOpen) {
  AddMountPoint(downloads_dir_);

  base::FilePath test_file =
      downloads_dir_.AppendASCII("file_manager_test.html");

  // Create an empty file to give us something to select.
  FILE* fp = base::OpenFile(test_file, "w");
  ASSERT_TRUE(fp != NULL);
  ASSERT_TRUE(base::CloseFile(fp));

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // Spawn a dialog to open a file.  Provide the path to the file so the dialog
  // will automatically select it.  Ensure that the OK button is enabled by
  // waiting for chrome.test.sendMessage('selection-change-complete').
  // The extension starts a Web Worker to read file metadata, so it may send
  // 'selection-change-complete' before 'worker-initialized'.  This is OK.
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     test_file, owning_window,
                                     "selection-change-complete"));

  // Click open button.
  CloseDialog(DIALOG_BTN_OK, owning_window);

  // Listener should have been informed that the file was opened.
  ASSERT_TRUE(listener_->file_selected());
  ASSERT_FALSE(listener_->canceled());
  ASSERT_EQ(test_file, listener_->path());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndSave) {
  AddMountPoint(downloads_dir_);

  base::FilePath test_file =
      downloads_dir_.AppendASCII("file_manager_test.html");

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // Spawn a dialog to save a file, providing a suggested path.
  // Ensure "Save" button is enabled by waiting for notification from
  // chrome.test.sendMessage().
  // The extension starts a Web Worker to read file metadata, so it may send
  // 'directory-change-complete' before 'worker-initialized'.  This is OK.
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
                                     test_file, owning_window,
                                     "directory-change-complete"));

  // Click save button.
  CloseDialog(DIALOG_BTN_OK, owning_window);

  // Listener should have been informed that the file was selected.
  ASSERT_TRUE(listener_->file_selected());
  ASSERT_FALSE(listener_->canceled());
  ASSERT_EQ(test_file, listener_->path());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       OpenSingletonTabAndCancel) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  // Open a singleton tab in background.
  chrome::NavigateParams p(browser(), GURL("http://www.google.com"),
                           ui::PAGE_TRANSITION_LINK);
  p.window_action = chrome::NavigateParams::SHOW_WINDOW;
  p.disposition = SINGLETON_TAB;
  chrome::Navigate(&p);

  // Press cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       OpenTwoDialogs) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  TryOpeningSecondDialog(owning_window);

  // Second dialog should not be running.
  ASSERT_FALSE(second_dialog_->IsRunning(owning_window));

  // Click cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}
<commit_msg>Files.app: Use "ready" message instead of "worker-initialized" for waiting initialization in SelectFileAndCancel test.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/select_file_dialog_extension.h"

#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/test/test_utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/selected_file_info.h"

using content::BrowserContext;

// Mock listener used by test below.
class MockSelectFileDialogListener : public ui::SelectFileDialog::Listener {
 public:
  MockSelectFileDialogListener()
    : file_selected_(false),
      canceled_(false),
      params_(NULL) {
  }

  bool file_selected() const { return file_selected_; }
  bool canceled() const { return canceled_; }
  base::FilePath path() const { return path_; }
  void* params() const { return params_; }

  // ui::SelectFileDialog::Listener implementation.
  virtual void FileSelected(const base::FilePath& path,
                            int index,
                            void* params) override {
    file_selected_ = true;
    path_ = path;
    params_ = params;
  }
  virtual void FileSelectedWithExtraInfo(
      const ui::SelectedFileInfo& selected_file_info,
      int index,
      void* params) override {
    FileSelected(selected_file_info.local_path, index, params);
  }
  virtual void MultiFilesSelected(
      const std::vector<base::FilePath>& files, void* params) override {}
  virtual void FileSelectionCanceled(void* params) override {
    canceled_ = true;
    params_ = params;
  }

 private:
  bool file_selected_;
  bool canceled_;
  base::FilePath path_;
  void* params_;

  DISALLOW_COPY_AND_ASSIGN(MockSelectFileDialogListener);
};

class SelectFileDialogExtensionBrowserTest : public ExtensionBrowserTest {
 public:
  enum DialogButtonType {
    DIALOG_BTN_OK,
    DIALOG_BTN_CANCEL
  };

  virtual void SetUp() override {
    extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();

    // Create the dialog wrapper object, but don't show it yet.
    listener_.reset(new MockSelectFileDialogListener());
    dialog_ = new SelectFileDialogExtension(listener_.get(), NULL);

    // We have to provide at least one mount point.
    // File manager looks for "Downloads" mount point, so use this name.
    base::FilePath tmp_path;
    PathService::Get(base::DIR_TEMP, &tmp_path);
    ASSERT_TRUE(tmp_dir_.CreateUniqueTempDirUnderPath(tmp_path));
    downloads_dir_ = tmp_dir_.path().Append("Downloads");
    base::CreateDirectory(downloads_dir_);

    // Must run after our setup because it actually runs the test.
    ExtensionBrowserTest::SetUp();
  }

  virtual void TearDown() override {
    ExtensionBrowserTest::TearDown();

    // Delete the dialog first, as it holds a pointer to the listener.
    dialog_ = NULL;
    listener_.reset();

    second_dialog_ = NULL;
    second_listener_.reset();
  }

  // Creates a file system mount point for a directory.
  void AddMountPoint(const base::FilePath& path) {
    EXPECT_TRUE(file_manager::VolumeManager::Get(
        browser()->profile())->RegisterDownloadsDirectoryForTesting(path));
    browser()->profile()->GetPrefs()->SetFilePath(
        prefs::kDownloadDefaultDirectory, downloads_dir_);
  }

  void CheckJavascriptErrors() {
    content::RenderFrameHost* host =
        dialog_->GetRenderViewHost()->GetMainFrame();
    scoped_ptr<base::Value> value =
        content::ExecuteScriptAndGetValue(host, "window.JSErrorCount");
    int js_error_count = 0;
    ASSERT_TRUE(value->GetAsInteger(&js_error_count));
    ASSERT_EQ(0, js_error_count);
  }

  void OpenDialog(ui::SelectFileDialog::Type dialog_type,
                  const base::FilePath& file_path,
                  const gfx::NativeWindow& owning_window,
                  const std::string& additional_message) {
    // Spawn a dialog to open a file.  The dialog will signal that it is ready
    // via chrome.test.sendMessage() in the extension JavaScript.
    ExtensionTestMessageListener init_listener("ready", false /* will_reply */);

    scoped_ptr<ExtensionTestMessageListener> additional_listener;
    if (!additional_message.empty()) {
      additional_listener.reset(
          new ExtensionTestMessageListener(additional_message, false));
    }

    dialog_->SelectFile(dialog_type,
                        base::string16() /* title */,
                        file_path,
                        NULL /* file_types */,
                         0 /* file_type_index */,
                        FILE_PATH_LITERAL("") /* default_extension */,
                        owning_window,
                        this /* params */);

    LOG(INFO) << "Waiting for JavaScript ready message.";
    ASSERT_TRUE(init_listener.WaitUntilSatisfied());

    if (additional_listener.get()) {
      LOG(INFO) << "Waiting for JavaScript " << additional_message
                << " message.";
      ASSERT_TRUE(additional_listener->WaitUntilSatisfied());
    }

    // Dialog should be running now.
    ASSERT_TRUE(dialog_->IsRunning(owning_window));

    ASSERT_NO_FATAL_FAILURE(CheckJavascriptErrors());
  }

  void TryOpeningSecondDialog(const gfx::NativeWindow& owning_window) {
    second_listener_.reset(new MockSelectFileDialogListener());
    second_dialog_ = new SelectFileDialogExtension(second_listener_.get(),
                                                   NULL);

    // At the moment we don't really care about dialog type, but we have to put
    // some dialog type.
    second_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
                               base::string16() /* title */,
                               base::FilePath() /* default_path */,
                               NULL /* file_types */,
                               0 /* file_type_index */,
                               FILE_PATH_LITERAL("") /* default_extension */,
                               owning_window,
                               this /* params */);
  }

  void CloseDialog(DialogButtonType button_type,
                   const gfx::NativeWindow& owning_window) {
    // Inject JavaScript to click the cancel button and wait for notification
    // that the window has closed.
    content::WindowedNotificationObserver host_destroyed(
        content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
        content::NotificationService::AllSources());
    content::RenderViewHost* host = dialog_->GetRenderViewHost();
    std::string button_class =
        (button_type == DIALOG_BTN_OK) ? ".button-panel .ok" :
                                         ".button-panel .cancel";
    base::string16 script = base::ASCIIToUTF16(
        "console.log(\'Test JavaScript injected.\');"
        "document.querySelector(\'" + button_class + "\').click();");
    // The file selection handler closes the dialog and does not return control
    // to JavaScript, so do not wait for return values.
    host->GetMainFrame()->ExecuteJavaScript(script);
    LOG(INFO) << "Waiting for window close notification.";
    host_destroyed.Wait();

    // Dialog no longer believes it is running.
    ASSERT_FALSE(dialog_->IsRunning(owning_window));
  }

  scoped_ptr<MockSelectFileDialogListener> listener_;
  scoped_refptr<SelectFileDialogExtension> dialog_;

  scoped_ptr<MockSelectFileDialogListener> second_listener_;
  scoped_refptr<SelectFileDialogExtension> second_dialog_;

  base::ScopedTempDir tmp_dir_;
  base::FilePath downloads_dir_;
};

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest, CreateAndDestroy) {
  // Browser window must be up for us to test dialog window parent.
  gfx::NativeWindow native_window = browser()->window()->GetNativeWindow();
  ASSERT_TRUE(native_window != NULL);

  // Before we call SelectFile, dialog is not running/visible.
  ASSERT_FALSE(dialog_->IsRunning(native_window));
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest, DestroyListener) {
  // Some users of SelectFileDialog destroy their listener before cleaning
  // up the dialog.  Make sure we don't crash.
  dialog_->ListenerDestroyed();
  listener_.reset();
}

// TODO(jamescook): Add a test for selecting a file for an <input type='file'/>
// page element, as that uses different memory management pathways.
// crbug.com/98791

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndCancel) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // base::FilePath() for default path.
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  // Press cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndOpen) {
  AddMountPoint(downloads_dir_);

  base::FilePath test_file =
      downloads_dir_.AppendASCII("file_manager_test.html");

  // Create an empty file to give us something to select.
  FILE* fp = base::OpenFile(test_file, "w");
  ASSERT_TRUE(fp != NULL);
  ASSERT_TRUE(base::CloseFile(fp));

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // Spawn a dialog to open a file.  Provide the path to the file so the dialog
  // will automatically select it.  Ensure that the OK button is enabled by
  // waiting for chrome.test.sendMessage('selection-change-complete').
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     test_file, owning_window,
                                     "selection-change-complete"));

  // Click open button.
  CloseDialog(DIALOG_BTN_OK, owning_window);

  // Listener should have been informed that the file was opened.
  ASSERT_TRUE(listener_->file_selected());
  ASSERT_FALSE(listener_->canceled());
  ASSERT_EQ(test_file, listener_->path());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       SelectFileAndSave) {
  AddMountPoint(downloads_dir_);

  base::FilePath test_file =
      downloads_dir_.AppendASCII("file_manager_test.html");

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  // Spawn a dialog to save a file, providing a suggested path.
  // Ensure "Save" button is enabled by waiting for notification from
  // chrome.test.sendMessage().
  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
                                     test_file, owning_window,
                                     "directory-change-complete"));

  // Click save button.
  CloseDialog(DIALOG_BTN_OK, owning_window);

  // Listener should have been informed that the file was selected.
  ASSERT_TRUE(listener_->file_selected());
  ASSERT_FALSE(listener_->canceled());
  ASSERT_EQ(test_file, listener_->path());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       OpenSingletonTabAndCancel) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  // Open a singleton tab in background.
  chrome::NavigateParams p(browser(), GURL("http://www.google.com"),
                           ui::PAGE_TRANSITION_LINK);
  p.window_action = chrome::NavigateParams::SHOW_WINDOW;
  p.disposition = SINGLETON_TAB;
  chrome::Navigate(&p);

  // Press cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}

IN_PROC_BROWSER_TEST_F(SelectFileDialogExtensionBrowserTest,
                       OpenTwoDialogs) {
  AddMountPoint(downloads_dir_);

  gfx::NativeWindow owning_window = browser()->window()->GetNativeWindow();

  ASSERT_NO_FATAL_FAILURE(OpenDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                                     base::FilePath(), owning_window, ""));

  TryOpeningSecondDialog(owning_window);

  // Second dialog should not be running.
  ASSERT_FALSE(second_dialog_->IsRunning(owning_window));

  // Click cancel button.
  CloseDialog(DIALOG_BTN_CANCEL, owning_window);

  // Listener should have been informed of the cancellation.
  ASSERT_FALSE(listener_->file_selected());
  ASSERT_TRUE(listener_->canceled());
  ASSERT_EQ(this, listener_->params());
}
<|endoftext|>


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

#include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"

#include <string>

#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/display/output_configurator_animation.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/chromeos/display/display_preferences.h"
#include "chrome/browser/chromeos/display/overscan_calibrator.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/display/output_configurator.h"
#include "content/public/browser/web_ui.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"

namespace chromeos {
namespace options {

DisplayOptionsHandler::DisplayOptionsHandler() {
  ash::Shell::GetScreen()->AddObserver(this);
}

DisplayOptionsHandler::~DisplayOptionsHandler() {
  ash::Shell::GetScreen()->RemoveObserver(this);
}

void DisplayOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  RegisterTitle(localized_strings, "displayOptionsPage",
                IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE);
  localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING));
  localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING));
  localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY));
  localized_strings->SetString("applyResult", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_APPLY_RESULT));
  localized_strings->SetString("resolution", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION));
  localized_strings->SetString(
      "startCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
  localized_strings->SetString(
      "finishCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_FINISH_CALIBRATING_OVERSCAN));
  localized_strings->SetString(
      "clearCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_CLEAR_CALIBRATING_OVERSCAN));
}

void DisplayOptionsHandler::InitializePage() {
  DCHECK(web_ui());
  UpdateDisplaySectionVisibility();
}

void DisplayOptionsHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback(
      "getDisplayInfo",
      base::Bind(&DisplayOptionsHandler::HandleDisplayInfo,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setMirroring",
      base::Bind(&DisplayOptionsHandler::HandleMirroring,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setPrimary",
      base::Bind(&DisplayOptionsHandler::HandleSetPrimary,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setDisplayLayout",
      base::Bind(&DisplayOptionsHandler::HandleDisplayLayout,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "startOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleStartOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "finishOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleFinishOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "clearOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleClearOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "updateOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleUpdateOverscanCalibration,
                 base::Unretained(this)));
}

void DisplayOptionsHandler::OnDisplayBoundsChanged(
    const gfx::Display& display) {
}

void DisplayOptionsHandler::OnDisplayAdded(const gfx::Display& new_display) {
  UpdateDisplaySectionVisibility();
  SendDisplayInfo();
}

void DisplayOptionsHandler::OnDisplayRemoved(const gfx::Display& old_display) {
  UpdateDisplaySectionVisibility();
  SendDisplayInfo();
}

void DisplayOptionsHandler::UpdateDisplaySectionVisibility() {
  chromeos::OutputState output_state =
      ash::Shell::GetInstance()->output_configurator()->output_state();
  base::FundamentalValue show_options(
      output_state != chromeos::STATE_INVALID &&
      output_state != chromeos::STATE_HEADLESS &&
      output_state != chromeos::STATE_SINGLE);
  web_ui()->CallJavascriptFunction(
      "options.BrowserOptions.showDisplayOptions", show_options);
}

void DisplayOptionsHandler::SendDisplayInfo() {
  ash::internal::DisplayManager* display_manager =
      ash::Shell::GetInstance()->display_manager();
  ash::DisplayController* display_controller =
      ash::Shell::GetInstance()->display_controller();
  chromeos::OutputConfigurator* output_configurator =
      ash::Shell::GetInstance()->output_configurator();
  base::FundamentalValue mirroring(
      output_configurator->output_state() == chromeos::STATE_DUAL_MIRROR);

  int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
  base::ListValue displays;
  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    const gfx::Display* display = display_manager->GetDisplayAt(i);
    const gfx::Rect& bounds = display->bounds();
    base::DictionaryValue* js_display = new base::DictionaryValue();
    js_display->SetString("id", base::Int64ToString(display->id()));
    js_display->SetDouble("x", bounds.x());
    js_display->SetDouble("y", bounds.y());
    js_display->SetDouble("width", bounds.width());
    js_display->SetDouble("height", bounds.height());
    js_display->SetString("name",
                          display_manager->GetDisplayNameFor(*display));
    js_display->SetBoolean("isPrimary", display->id() == primary_id);
    base::DictionaryValue* js_insets = new base::DictionaryValue();
    const gfx::Insets& insets =
        display_controller->GetOverscanInsets(display->id());
    js_insets->SetInteger("top", insets.top());
    js_insets->SetInteger("left", insets.left());
    js_insets->SetInteger("bottom", insets.bottom());
    js_insets->SetInteger("right", insets.right());
    js_display->Set("overscan", js_insets);
    displays.Set(i, js_display);
  }

  scoped_ptr<base::Value> layout_value(base::Value::CreateNullValue());
  scoped_ptr<base::Value> offset_value(base::Value::CreateNullValue());
  if (display_manager->GetNumDisplays() > 1) {
    const gfx::Display secondary_display =
        ash::ScreenAsh::GetSecondaryDisplay();
    const ash::DisplayLayout& layout =
        display_controller->GetLayoutForDisplay(secondary_display);
    layout_value.reset(new base::FundamentalValue(layout.position));
    offset_value.reset(new base::FundamentalValue(layout.offset));
  }

  web_ui()->CallJavascriptFunction(
      "options.DisplayOptions.setDisplayInfo",
      mirroring, displays, *layout_value.get(), *offset_value.get());
}

void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
  // We use 'PRIMARY_ONLY' for non-mirroring state for now.
  // TODO(mukai): fix this and support multiple display modes.
  chromeos::OutputState new_state =
      is_mirroring ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY;
  ash::Shell::GetInstance()->output_configurator()->SetDisplayMode(new_state);
  SendDisplayInfo();
  // Not necessary to start fade-in animation.  OutputConfigurator will do that.
}

void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
    int layout, int offset) {
  PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
  const gfx::Display& secondary_display = ash::ScreenAsh::GetSecondaryDisplay();
  if (secondary_display.is_valid())
    SetDisplayLayoutPref(pref_service, secondary_display, layout, offset);

  SendDisplayInfo();
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeInAnimation();
}

void DisplayOptionsHandler::HandleDisplayInfo(
    const base::ListValue* unused_args) {
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
  DCHECK(!args->empty());
  bool is_mirroring = false;
  args->GetBoolean(0, &is_mirroring);
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeOutAnimation(base::Bind(
          &DisplayOptionsHandler::OnFadeOutForMirroringFinished,
          base::Unretained(this),
          is_mirroring));
}

void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
  DCHECK(!args->empty());

  int64 display_id = gfx::Display::kInvalidDisplayID;
  std::string id_value;
  if (!args->GetString(0, &id_value)) {
    LOG(ERROR) << "Can't find ID";
    return;
  }

  if (!base::StringToInt64(id_value, &display_id) ||
      display_id == gfx::Display::kInvalidDisplayID) {
    LOG(ERROR) << "Invalid parameter: " << id_value;
    return;
  }

  SetPrimaryDisplayIDPref(display_id);
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
  double layout = -1;
  double offset = -1;
  if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) {
    LOG(ERROR) << "Invalid parameter";
    SendDisplayInfo();
    return;
  }
  DCHECK_LE(ash::DisplayLayout::TOP, layout);
  DCHECK_GE(ash::DisplayLayout::LEFT, layout);
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeOutAnimation(base::Bind(
          &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
          base::Unretained(this),
          static_cast<int>(layout),
          static_cast<int>(offset)));
}

void DisplayOptionsHandler::HandleStartOverscanCalibration(
    const base::ListValue* args) {
  int64 display_id = gfx::Display::kInvalidDisplayID;
  std::string id_value;
  if (!args->GetString(0, &id_value)) {
    LOG(ERROR) << "Can't find ID";
    return;
  }
  if (!base::StringToInt64(id_value, &display_id) ||
      display_id == gfx::Display::kInvalidDisplayID) {
    LOG(ERROR) << "Invalid parameter: " << id_value;
    return;
  }

  const gfx::Display& display = ash::ScreenAsh::GetDisplayForId(display_id);
  DCHECK(display.is_valid());
  ash::DisplayController* display_controller =
      ash::Shell::GetInstance()->display_controller();
  overscan_calibrator_.reset(new OverscanCalibrator(
      display,
      display_controller->GetOverscanInsets(display_id)));
}

void DisplayOptionsHandler::HandleFinishOverscanCalibration(
    const base::ListValue* args) {
  DCHECK(overscan_calibrator_.get());
  overscan_calibrator_->Commit();
  overscan_calibrator_.reset();
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleClearOverscanCalibration(
    const base::ListValue* args) {
  DCHECK(overscan_calibrator_.get());
  overscan_calibrator_->UpdateInsets(gfx::Insets());
  overscan_calibrator_->Commit();
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleUpdateOverscanCalibration(
    const base::ListValue* args) {
  DCHECK(overscan_calibrator_.get());
  double top = 0, left = 0, bottom = 0, right = 0;
  if (!args->GetDouble(0, &top) || !args->GetDouble(1, &left) ||
      !args->GetDouble(2, &bottom) || !args->GetDouble(3, &right)) {
    LOG(ERROR) << "Can't find overscan insets data.";
    return;
  }

  overscan_calibrator_->UpdateInsets(gfx::Insets(top, left, bottom, right));
}

}  // namespace options
}  // namespace chromeos
<commit_msg>Adds a usual check for overscan_calibrator_ rather than DCHECK.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"

#include <string>

#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/display/output_configurator_animation.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/chromeos/display/display_preferences.h"
#include "chrome/browser/chromeos/display/overscan_calibrator.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/display/output_configurator.h"
#include "content/public/browser/web_ui.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"

namespace chromeos {
namespace options {

DisplayOptionsHandler::DisplayOptionsHandler() {
  ash::Shell::GetScreen()->AddObserver(this);
}

DisplayOptionsHandler::~DisplayOptionsHandler() {
  ash::Shell::GetScreen()->RemoveObserver(this);
}

void DisplayOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  RegisterTitle(localized_strings, "displayOptionsPage",
                IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE);
  localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING));
  localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING));
  localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY));
  localized_strings->SetString("applyResult", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_APPLY_RESULT));
  localized_strings->SetString("resolution", l10n_util::GetStringUTF16(
      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION));
  localized_strings->SetString(
      "startCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
  localized_strings->SetString(
      "finishCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_FINISH_CALIBRATING_OVERSCAN));
  localized_strings->SetString(
      "clearCalibratingOverscan", l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_CLEAR_CALIBRATING_OVERSCAN));
}

void DisplayOptionsHandler::InitializePage() {
  DCHECK(web_ui());
  UpdateDisplaySectionVisibility();
}

void DisplayOptionsHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback(
      "getDisplayInfo",
      base::Bind(&DisplayOptionsHandler::HandleDisplayInfo,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setMirroring",
      base::Bind(&DisplayOptionsHandler::HandleMirroring,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setPrimary",
      base::Bind(&DisplayOptionsHandler::HandleSetPrimary,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setDisplayLayout",
      base::Bind(&DisplayOptionsHandler::HandleDisplayLayout,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "startOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleStartOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "finishOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleFinishOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "clearOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleClearOverscanCalibration,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "updateOverscanCalibration",
      base::Bind(&DisplayOptionsHandler::HandleUpdateOverscanCalibration,
                 base::Unretained(this)));
}

void DisplayOptionsHandler::OnDisplayBoundsChanged(
    const gfx::Display& display) {
}

void DisplayOptionsHandler::OnDisplayAdded(const gfx::Display& new_display) {
  UpdateDisplaySectionVisibility();
  SendDisplayInfo();
}

void DisplayOptionsHandler::OnDisplayRemoved(const gfx::Display& old_display) {
  UpdateDisplaySectionVisibility();
  SendDisplayInfo();
}

void DisplayOptionsHandler::UpdateDisplaySectionVisibility() {
  chromeos::OutputState output_state =
      ash::Shell::GetInstance()->output_configurator()->output_state();
  base::FundamentalValue show_options(
      output_state != chromeos::STATE_INVALID &&
      output_state != chromeos::STATE_HEADLESS &&
      output_state != chromeos::STATE_SINGLE);
  web_ui()->CallJavascriptFunction(
      "options.BrowserOptions.showDisplayOptions", show_options);
}

void DisplayOptionsHandler::SendDisplayInfo() {
  ash::internal::DisplayManager* display_manager =
      ash::Shell::GetInstance()->display_manager();
  ash::DisplayController* display_controller =
      ash::Shell::GetInstance()->display_controller();
  chromeos::OutputConfigurator* output_configurator =
      ash::Shell::GetInstance()->output_configurator();
  base::FundamentalValue mirroring(
      output_configurator->output_state() == chromeos::STATE_DUAL_MIRROR);

  int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
  base::ListValue displays;
  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    const gfx::Display* display = display_manager->GetDisplayAt(i);
    const gfx::Rect& bounds = display->bounds();
    base::DictionaryValue* js_display = new base::DictionaryValue();
    js_display->SetString("id", base::Int64ToString(display->id()));
    js_display->SetDouble("x", bounds.x());
    js_display->SetDouble("y", bounds.y());
    js_display->SetDouble("width", bounds.width());
    js_display->SetDouble("height", bounds.height());
    js_display->SetString("name",
                          display_manager->GetDisplayNameFor(*display));
    js_display->SetBoolean("isPrimary", display->id() == primary_id);
    base::DictionaryValue* js_insets = new base::DictionaryValue();
    const gfx::Insets& insets =
        display_controller->GetOverscanInsets(display->id());
    js_insets->SetInteger("top", insets.top());
    js_insets->SetInteger("left", insets.left());
    js_insets->SetInteger("bottom", insets.bottom());
    js_insets->SetInteger("right", insets.right());
    js_display->Set("overscan", js_insets);
    displays.Set(i, js_display);
  }

  scoped_ptr<base::Value> layout_value(base::Value::CreateNullValue());
  scoped_ptr<base::Value> offset_value(base::Value::CreateNullValue());
  if (display_manager->GetNumDisplays() > 1) {
    const gfx::Display secondary_display =
        ash::ScreenAsh::GetSecondaryDisplay();
    const ash::DisplayLayout& layout =
        display_controller->GetLayoutForDisplay(secondary_display);
    layout_value.reset(new base::FundamentalValue(layout.position));
    offset_value.reset(new base::FundamentalValue(layout.offset));
  }

  web_ui()->CallJavascriptFunction(
      "options.DisplayOptions.setDisplayInfo",
      mirroring, displays, *layout_value.get(), *offset_value.get());
}

void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
  // We use 'PRIMARY_ONLY' for non-mirroring state for now.
  // TODO(mukai): fix this and support multiple display modes.
  chromeos::OutputState new_state =
      is_mirroring ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY;
  ash::Shell::GetInstance()->output_configurator()->SetDisplayMode(new_state);
  SendDisplayInfo();
  // Not necessary to start fade-in animation.  OutputConfigurator will do that.
}

void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
    int layout, int offset) {
  PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
  const gfx::Display& secondary_display = ash::ScreenAsh::GetSecondaryDisplay();
  if (secondary_display.is_valid())
    SetDisplayLayoutPref(pref_service, secondary_display, layout, offset);

  SendDisplayInfo();
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeInAnimation();
}

void DisplayOptionsHandler::HandleDisplayInfo(
    const base::ListValue* unused_args) {
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
  DCHECK(!args->empty());
  bool is_mirroring = false;
  args->GetBoolean(0, &is_mirroring);
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeOutAnimation(base::Bind(
          &DisplayOptionsHandler::OnFadeOutForMirroringFinished,
          base::Unretained(this),
          is_mirroring));
}

void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
  DCHECK(!args->empty());

  int64 display_id = gfx::Display::kInvalidDisplayID;
  std::string id_value;
  if (!args->GetString(0, &id_value)) {
    LOG(ERROR) << "Can't find ID";
    return;
  }

  if (!base::StringToInt64(id_value, &display_id) ||
      display_id == gfx::Display::kInvalidDisplayID) {
    LOG(ERROR) << "Invalid parameter: " << id_value;
    return;
  }

  SetPrimaryDisplayIDPref(display_id);
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
  double layout = -1;
  double offset = -1;
  if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) {
    LOG(ERROR) << "Invalid parameter";
    SendDisplayInfo();
    return;
  }
  DCHECK_LE(ash::DisplayLayout::TOP, layout);
  DCHECK_GE(ash::DisplayLayout::LEFT, layout);
  ash::Shell::GetInstance()->output_configurator_animation()->
      StartFadeOutAnimation(base::Bind(
          &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
          base::Unretained(this),
          static_cast<int>(layout),
          static_cast<int>(offset)));
}

void DisplayOptionsHandler::HandleStartOverscanCalibration(
    const base::ListValue* args) {
  int64 display_id = gfx::Display::kInvalidDisplayID;
  std::string id_value;
  if (!args->GetString(0, &id_value)) {
    LOG(ERROR) << "Can't find ID";
    return;
  }
  if (!base::StringToInt64(id_value, &display_id) ||
      display_id == gfx::Display::kInvalidDisplayID) {
    LOG(ERROR) << "Invalid parameter: " << id_value;
    return;
  }

  const gfx::Display& display = ash::ScreenAsh::GetDisplayForId(display_id);
  DCHECK(display.is_valid());
  ash::DisplayController* display_controller =
      ash::Shell::GetInstance()->display_controller();
  overscan_calibrator_.reset(new OverscanCalibrator(
      display,
      display_controller->GetOverscanInsets(display_id)));
}

void DisplayOptionsHandler::HandleFinishOverscanCalibration(
    const base::ListValue* args) {
  if (overscan_calibrator_.get()) {
    overscan_calibrator_->Commit();
    overscan_calibrator_.reset();
  }
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleClearOverscanCalibration(
    const base::ListValue* args) {
  if (overscan_calibrator_.get()) {
    overscan_calibrator_->UpdateInsets(gfx::Insets());
    overscan_calibrator_->Commit();
  }
  SendDisplayInfo();
}

void DisplayOptionsHandler::HandleUpdateOverscanCalibration(
    const base::ListValue* args) {
  if (!overscan_calibrator_.get())
    return;

  double top = 0, left = 0, bottom = 0, right = 0;
  if (!args->GetDouble(0, &top) || !args->GetDouble(1, &left) ||
      !args->GetDouble(2, &bottom) || !args->GetDouble(3, &right)) {
    LOG(ERROR) << "Can't find overscan insets data.";
    return;
  }

  overscan_calibrator_->UpdateInsets(gfx::Insets(top, left, bottom, right));
}

}  // namespace options
}  // namespace chromeos
<|endoftext|>