<commit_before>/******************************************************************************
 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
 *                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
 *                                                                             *
 * This program is free software; you can redistribute it and/or modify it     *
 * under the terms of the GNU General Public License as published by the Free  *
 * Software Foundation; either version 2 of the License, or (at your option)   *
 * any later version.                                                          *
 *                                                                             *
 * This program is distributed in the hope that it will be useful, but WITHOUT *
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
 * more details.                                                               *
 *                                                                             *
 * You should have received a copy of the GNU General Public License along     *
 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
 *******************************************************************************
 *                            SOFA :: Applications                             *
 *                                                                             *
 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
 *                                                                             *
 * Contact information: contact@sofa-framework.org                             *
 ******************************************************************************/
#include <sofa/simulation/tree/TreeSimulation.h>
#include <sofa/simulation/tree/GNode.h>
#include <sofa/component/misc/ReadState.h>
#include <sofa/component/misc/WriteState.h>
#include <sofa/component/misc/CompareState.h>
#include <sofa/component/misc/ReadTopology.h>
#include <sofa/component/misc/WriteTopology.h>
#include <sofa/component/misc/CompareTopology.h>
#include <sofa/component/init.h>
#include <sofa/helper/system/thread/TimeoutWatchdog.h>
#include <sofa/helper/system/FileRepository.h>
#include <sofa/helper/system/SetDirectory.h>
#include <sofa/helper/ArgumentParser.h>
#include <sofa/helper/Factory.h>
#include <sofa/helper/BackTrace.h>
#include <iostream>
#include <fstream>
#include <ctime>

using sofa::helper::system::DataRepository;
using sofa::helper::system::SetDirectory;
using sofa::simulation::tree::GNode;

#ifndef WIN32
#include <dlfcn.h>
bool loadPlugin(const char* filename)
{
    void *handle;
    handle=dlopen(filename, RTLD_LAZY);
    if (!handle)
    {
        std::cerr<<"Error loading plugin "<<filename<<": "<<dlerror()<<std::endl;
        return false;
    }
    std::cerr<<"Plugin "<<filename<<" loaded."<<std::endl;
    return true;
}
#else
bool loadPlugin(const char* filename)
{
    HINSTANCE DLLHandle;
    DLLHandle = LoadLibraryA(filename); //warning: issue between unicode and ansi encoding on Visual c++ -> force to ansi-> dirty!
    if (DLLHandle == NULL)
    {
        std::cerr<<"Error loading plugin "<<filename<<std::endl;
        return false;
    }
    std::cerr<<"Plugin "<<filename<<" loaded."<<std::endl;
    return true;
}
#endif

// ---------------------------------------------------------------------
// ---
// ---------------------------------------------------------------------

void apply(const std::string& directory, std::vector<std::string>& files, bool reinit)
{

    sofa::component::init(); // ensures all components are initialized, also introduce a dependency to all libraries, avoiding problems with -Wl,--as-needed flag

    sofa::simulation::Simulation* simulation = sofa::simulation::getSimulation();

    //Launch the comparison for each scenes
    for (unsigned int i = 0; i < files.size(); ++i)
    {

        const std::string& currentFile = files[i];
        GNode* groot = dynamic_cast<GNode*> (simulation->load(currentFile.c_str()));
        if (groot == NULL)
        {
            std::cerr << "CANNOT open " << currentFile << " !" << std::endl;
            continue;
        }
        std::cout << "sec. Loading " << currentFile << std::endl;

        //Save the initial time
        clock_t curtime = clock();
        simulation->init(groot);
        double t = static_cast<double>(clock() - curtime) / (float)CLOCKS_PER_SEC;
        std::cout << "Init time " << t << " sec." << std::endl;

        //Clear and prepare for next scene
        simulation->unload(groot);
        delete groot;
    }
}

int main(int argc, char** argv)
{
    sofa::helper::BackTrace::autodump();

    std::string refdir;
    std::string dataPath;
    std::vector<std::string> fileArguments;
    std::vector<std::string> sceneFiles;
    std::vector<std::string> plugins;
    bool reinit = false;
    unsigned lifetime = 0;

    sofa::simulation::setSimulation(new sofa::simulation::tree::TreeSimulation());

    sofa::helper::parse(
        &fileArguments,
        "This is SOFA verification. "
        "To use it, specify in the command line the scene files you want to test, "
        "or a \".ini\" file containing the path to the scenes.")
    .option(&reinit,     'r', "reinit",    "Recreate the references state files")
    .option(&refdir,     'd', "refdir",    "The directory for reference files")
    .option(&dataPath,   'a', "datapath",  "A colon-separated (semi-colon on Windows) list of directories to search for data files (scenes, resources...)")
    .option(&plugins,    'p', "plugin",    "Load given plugins")
    .option(&lifetime,   'l', "lifetime",  "Maximum execution time in seconds (default: 0 -> no limit")
    (argc, argv);

#ifdef SOFA_HAVE_BOOST
    sofa::helper::system::thread::TimeoutWatchdog watchdog;
    if(lifetime > 0)
    {
        watchdog.start(lifetime);
    }
#endif

    for(unsigned int i = 0; i < plugins.size(); i++)
    {
        loadPlugin(plugins[i].c_str());
    }

    DataRepository.addLastPath(dataPath);
    for(size_t i = 0; i < fileArguments.size(); ++i)
    {
        std::string currentFile = fileArguments[i];
        DataRepository.findFile(currentFile);

        if (currentFile.compare(currentFile.size() - 4, 4, ".ini") == 0)
        {
            //This is an ini file: get the list of scenes to test
            std::ifstream iniFileStream(currentFile.c_str());
            while (!iniFileStream.eof())
            {
                std::string line;
                std::string currentScene;
                // extracting the filename line by line because each line can contain
                // extra data, ignored by this program but that may be useful for
                // other tools.
                getline(iniFileStream, line);
                std::istringstream lineStream(line);
                lineStream >> currentScene;
                DataRepository.findFile(currentScene);
                sceneFiles.push_back(currentScene);
            }
        }
        else
        {
            // this is supposed to be a scene file
            sceneFiles.push_back(currentFile);
        }
    }

    std::cout
            << "*********************************************************************\n"
                    << "******* Arguments ***************************************************\n"
                    << "reinit: "      << reinit     << '\n'
                    << "files : "                    << '\n';
    for(size_t i = 0; i < sceneFiles.size(); ++i)
    {
        std::cout << "  " << sceneFiles[i] << '\n';
    }

    apply(refdir, sceneFiles, reinit);

    return 0;
}
<commit_msg>r9979/sofa-dev : FIX: some warnings<commit_after>/******************************************************************************
 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
 *                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
 *                                                                             *
 * This program is free software; you can redistribute it and/or modify it     *
 * under the terms of the GNU General Public License as published by the Free  *
 * Software Foundation; either version 2 of the License, or (at your option)   *
 * any later version.                                                          *
 *                                                                             *
 * This program is distributed in the hope that it will be useful, but WITHOUT *
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
 * more details.                                                               *
 *                                                                             *
 * You should have received a copy of the GNU General Public License along     *
 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
 *******************************************************************************
 *                            SOFA :: Applications                             *
 *                                                                             *
 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
 *                                                                             *
 * Contact information: contact@sofa-framework.org                             *
 ******************************************************************************/
#include <sofa/simulation/tree/TreeSimulation.h>
#include <sofa/simulation/tree/GNode.h>
#include <sofa/component/misc/ReadState.h>
#include <sofa/component/misc/WriteState.h>
#include <sofa/component/misc/CompareState.h>
#include <sofa/component/misc/ReadTopology.h>
#include <sofa/component/misc/WriteTopology.h>
#include <sofa/component/misc/CompareTopology.h>
#include <sofa/component/init.h>
#include <sofa/helper/system/thread/TimeoutWatchdog.h>
#include <sofa/helper/system/FileRepository.h>
#include <sofa/helper/system/SetDirectory.h>
#include <sofa/helper/ArgumentParser.h>
#include <sofa/helper/Factory.h>
#include <sofa/helper/BackTrace.h>
#include <iostream>
#include <fstream>
#include <ctime>

using sofa::helper::system::DataRepository;
using sofa::helper::system::SetDirectory;
using sofa::simulation::tree::GNode;

#ifndef WIN32
#include <dlfcn.h>
bool loadPlugin(const char* filename)
{
    void *handle;
    handle=dlopen(filename, RTLD_LAZY);
    if (!handle)
    {
        std::cerr<<"Error loading plugin "<<filename<<": "<<dlerror()<<std::endl;
        return false;
    }
    std::cerr<<"Plugin "<<filename<<" loaded."<<std::endl;
    return true;
}
#else
bool loadPlugin(const char* filename)
{
    HINSTANCE DLLHandle;
    DLLHandle = LoadLibraryA(filename); //warning: issue between unicode and ansi encoding on Visual c++ -> force to ansi-> dirty!
    if (DLLHandle == NULL)
    {
        std::cerr<<"Error loading plugin "<<filename<<std::endl;
        return false;
    }
    std::cerr<<"Plugin "<<filename<<" loaded."<<std::endl;
    return true;
}
#endif

// ---------------------------------------------------------------------
// ---
// ---------------------------------------------------------------------

void apply(const std::string& /*directory*/, std::vector<std::string>& files, bool /*reinit*/)
{

    sofa::component::init(); // ensures all components are initialized, also introduce a dependency to all libraries, avoiding problems with -Wl,--as-needed flag

    sofa::simulation::Simulation* simulation = sofa::simulation::getSimulation();

    //Launch the comparison for each scenes
    for (unsigned int i = 0; i < files.size(); ++i)
    {

        const std::string& currentFile = files[i];
        GNode* groot = dynamic_cast<GNode*> (simulation->load(currentFile.c_str()));
        if (groot == NULL)
        {
            std::cerr << "CANNOT open " << currentFile << " !" << std::endl;
            continue;
        }
        std::cout << "sec. Loading " << currentFile << std::endl;

        //Save the initial time
        clock_t curtime = clock();
        simulation->init(groot);
        double t = static_cast<double>(clock() - curtime) / (float)CLOCKS_PER_SEC;
        std::cout << "Init time " << t << " sec." << std::endl;

        //Clear and prepare for next scene
        simulation->unload(groot);
        delete groot;
    }
}

int main(int argc, char** argv)
{
    sofa::helper::BackTrace::autodump();

    std::string refdir;
    std::string dataPath;
    std::vector<std::string> fileArguments;
    std::vector<std::string> sceneFiles;
    std::vector<std::string> plugins;
    bool reinit = false;
    unsigned lifetime = 0;

    sofa::simulation::setSimulation(new sofa::simulation::tree::TreeSimulation());

    sofa::helper::parse(
        &fileArguments,
        "This is SOFA verification. "
        "To use it, specify in the command line the scene files you want to test, "
        "or a \".ini\" file containing the path to the scenes.")
    .option(&reinit,     'r', "reinit",    "Recreate the references state files")
    .option(&refdir,     'd', "refdir",    "The directory for reference files")
    .option(&dataPath,   'a', "datapath",  "A colon-separated (semi-colon on Windows) list of directories to search for data files (scenes, resources...)")
    .option(&plugins,    'p', "plugin",    "Load given plugins")
    .option(&lifetime,   'l', "lifetime",  "Maximum execution time in seconds (default: 0 -> no limit")
    (argc, argv);

#ifdef SOFA_HAVE_BOOST
    sofa::helper::system::thread::TimeoutWatchdog watchdog;
    if(lifetime > 0)
    {
        watchdog.start(lifetime);
    }
#endif

    for(unsigned int i = 0; i < plugins.size(); i++)
    {
        loadPlugin(plugins[i].c_str());
    }

    DataRepository.addLastPath(dataPath);
    for(size_t i = 0; i < fileArguments.size(); ++i)
    {
        std::string currentFile = fileArguments[i];
        DataRepository.findFile(currentFile);

        if (currentFile.compare(currentFile.size() - 4, 4, ".ini") == 0)
        {
            //This is an ini file: get the list of scenes to test
            std::ifstream iniFileStream(currentFile.c_str());
            while (!iniFileStream.eof())
            {
                std::string line;
                std::string currentScene;
                // extracting the filename line by line because each line can contain
                // extra data, ignored by this program but that may be useful for
                // other tools.
                getline(iniFileStream, line);
                std::istringstream lineStream(line);
                lineStream >> currentScene;
                DataRepository.findFile(currentScene);
                sceneFiles.push_back(currentScene);
            }
        }
        else
        {
            // this is supposed to be a scene file
            sceneFiles.push_back(currentFile);
        }
    }

    std::cout
            << "*********************************************************************\n"
                    << "******* Arguments ***************************************************\n"
                    << "reinit: "      << reinit     << '\n'
                    << "files : "                    << '\n';
    for(size_t i = 0; i < sceneFiles.size(); ++i)
    {
        std::cout << "  " << sceneFiles[i] << '\n';
    }

    apply(refdir, sceneFiles, reinit);

    return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011-2013                                                    *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation; either version 2.1 of the License,               *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef CPPA_PROJECTION_HPP
#define CPPA_PROJECTION_HPP

#include "cppa/optional.hpp"
#include "cppa/guard_expr.hpp"

#include "cppa/util/call.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/left_or_right.hpp"

#include "cppa/detail/tdata.hpp"

namespace cppa { namespace detail {

template<typename Fun, typename Tuple, long... Is>
inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) {
    return f.defined_at(get_cv_aware<Is>(tup)...);
}

template<typename ProjectionFuns, typename... Ts>
struct collected_args_tuple {
    typedef typename tdata_from_type_list<
            typename util::tl_zip<
                typename util::tl_map<
                    ProjectionFuns,
                    util::map_to_result_type,
                    util::rm_optional
                >::type,
                typename util::tl_map<
                    util::type_list<Ts...>,
                    mutable_gref_wrapped
                >::type,
                util::left_or_right
            >::type
        >::type
        type;
};

template<typename Fun>
struct is_void_fun {
    static constexpr bool value = std::is_same<typename Fun::result_type, void>::value;
};

/**
 * @brief Projection implemented by a set of functors.
 */
template<class ProjectionFuns, typename... Ts>
class projection {

 public:

    typedef typename tdata_from_type_list<ProjectionFuns>::type fun_container;

    projection() = default;

    projection(fun_container&& args) : m_funs(std::move(args)) { }

    projection(const fun_container& args) : m_funs(args) { }

    projection(const projection&) = default;

    /**
     * @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
     *        the result of @p fun in @p result.
     */
    /*
    template<class PartFun>
    bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
        typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
        if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
            auto indices = util::get_indices(pargs);
            if (is_defined_at(fun, pargs, indices)) {
                result = util::apply_args(fun, pargs, indices);
                return true;
            }
        }
        return false;
    }
    */

    /**
     * @brief Invokes @p fun with a projection of <tt>args...</tt>.
     */
    template<class PartFun>
    optional<typename PartFun::result_type> operator()(PartFun& fun, Ts... args) const {
        typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
        auto indices = util::get_indices(pargs);
        if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
            if (is_defined_at(fun, pargs, indices)) {
                return util::apply_args(fun, pargs, indices);
            }
        }
        return none;
    }

 private:

    template<typename Storage, typename T>
    static inline  bool store(Storage& storage, T&& value) {
        storage = std::forward<T>(value);
        return true;
    }

    template<class Storage>
    static inline bool store(Storage& storage, optional<Storage>&& value) {
        if (value) {
            storage = std::move(*value);
            return true;
        }
        return false;
    }

    template<typename T>
    static inline auto fetch(const unit_t&, T&& arg)
    -> decltype(std::forward<T>(arg)) {
        return std::forward<T>(arg);
    }

    template<typename Fun, typename T>
    static inline auto fetch(const Fun& fun, T&& arg)
    -> decltype(fun(std::forward<T>(arg))) {
        return fun(std::forward<T>(arg));
    }

    static inline bool collect(tdata<>&, const tdata<>&) {
        return true;
    }

    template<class TData, class Trans, typename U, typename... Us>
    static inline bool collect(TData& td, const Trans& tr,
                               U&& arg, Us&&... args) {
        return    store(td.head, fetch(tr.head, std::forward<U>(arg)))
               && collect(td.tail(), tr.tail(), std::forward<Us>(args)...);
    }

    fun_container m_funs;

};

template<>
class projection<util::empty_type_list> {

 public:

    projection() = default;
    projection(const tdata<>&) { }
    projection(const projection&) = default;

    template<class PartFun>
    optional<typename PartFun::result_type> operator()(PartFun& fun) const {
        if (fun.defined_at()) {
            return fun();
        }
        return none;
    }

};

template<class ProjectionFuns, class List>
struct projection_from_type_list;

template<class ProjectionFuns, typename... Ts>
struct projection_from_type_list<ProjectionFuns, util::type_list<Ts...> > {
    typedef projection<ProjectionFuns, Ts...> type;
};

} } // namespace cppa::detail

#endif // CPPA_PROJECTION_HPP
<commit_msg>typedef arg types in detail::projection<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011-2013                                                    *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation; either version 2.1 of the License,               *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef CPPA_PROJECTION_HPP
#define CPPA_PROJECTION_HPP

#include "cppa/optional.hpp"
#include "cppa/guard_expr.hpp"

#include "cppa/util/call.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/left_or_right.hpp"

#include "cppa/detail/tdata.hpp"

namespace cppa { namespace detail {

template<typename Fun, typename Tuple, long... Is>
inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) {
    return f.defined_at(get_cv_aware<Is>(tup)...);
}

template<typename ProjectionFuns, typename... Ts>
struct collected_args_tuple {
    typedef typename tdata_from_type_list<
            typename util::tl_zip<
                typename util::tl_map<
                    ProjectionFuns,
                    util::map_to_result_type,
                    util::rm_optional
                >::type,
                typename util::tl_map<
                    util::type_list<Ts...>,
                    mutable_gref_wrapped
                >::type,
                util::left_or_right
            >::type
        >::type
        type;
};

template<typename Fun>
struct is_void_fun {
    static constexpr bool value = std::is_same<typename Fun::result_type, void>::value;
};

/**
 * @brief Projection implemented by a set of functors.
 */
template<class ProjectionFuns, typename... Ts>
class projection {

 public:

    typedef typename tdata_from_type_list<ProjectionFuns>::type fun_container;

    typedef util::type_list<typename util::rm_const_and_ref<Ts>::type...> arg_types;

    projection() = default;

    projection(fun_container&& args) : m_funs(std::move(args)) { }

    projection(const fun_container& args) : m_funs(args) { }

    projection(const projection&) = default;

    /**
     * @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
     *        the result of @p fun in @p result.
     */
    /*
    template<class PartFun>
    bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
        typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
        if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
            auto indices = util::get_indices(pargs);
            if (is_defined_at(fun, pargs, indices)) {
                result = util::apply_args(fun, pargs, indices);
                return true;
            }
        }
        return false;
    }
    */

    /**
     * @brief Invokes @p fun with a projection of <tt>args...</tt>.
     */
    template<class PartFun>
    optional<typename PartFun::result_type> operator()(PartFun& fun, Ts... args) const {
        typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
        auto indices = util::get_indices(pargs);
        if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
            if (is_defined_at(fun, pargs, indices)) {
                return util::apply_args(fun, pargs, indices);
            }
        }
        return none;
    }

 private:

    template<typename Storage, typename T>
    static inline  bool store(Storage& storage, T&& value) {
        storage = std::forward<T>(value);
        return true;
    }

    template<class Storage>
    static inline bool store(Storage& storage, optional<Storage>&& value) {
        if (value) {
            storage = std::move(*value);
            return true;
        }
        return false;
    }

    template<typename T>
    static inline auto fetch(const unit_t&, T&& arg)
    -> decltype(std::forward<T>(arg)) {
        return std::forward<T>(arg);
    }

    template<typename Fun, typename T>
    static inline auto fetch(const Fun& fun, T&& arg)
    -> decltype(fun(std::forward<T>(arg))) {
        return fun(std::forward<T>(arg));
    }

    static inline bool collect(tdata<>&, const tdata<>&) {
        return true;
    }

    template<class TData, class Trans, typename U, typename... Us>
    static inline bool collect(TData& td, const Trans& tr,
                               U&& arg, Us&&... args) {
        return    store(td.head, fetch(tr.head, std::forward<U>(arg)))
               && collect(td.tail(), tr.tail(), std::forward<Us>(args)...);
    }

    fun_container m_funs;

};

template<>
class projection<util::empty_type_list> {

 public:

    projection() = default;
    projection(const tdata<>&) { }
    projection(const projection&) = default;

    template<class PartFun>
    optional<typename PartFun::result_type> operator()(PartFun& fun) const {
        if (fun.defined_at()) {
            return fun();
        }
        return none;
    }

};

template<class ProjectionFuns, class List>
struct projection_from_type_list;

template<class ProjectionFuns, typename... Ts>
struct projection_from_type_list<ProjectionFuns, util::type_list<Ts...> > {
    typedef projection<ProjectionFuns, Ts...> type;
};

} } // namespace cppa::detail

#endif // CPPA_PROJECTION_HPP
<|endoftext|>


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

#include "base/ref_counted.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/extensions/autoupdate_interceptor.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/extension_updater.h"
#include "chrome/browser/profile.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"

class ExtensionManagementTest : public ExtensionBrowserTest {
 protected:
  // Helper method that returns whether the extension is at the given version.
  // This calls version(), which must be defined in the extension's bg page,
  // as well as asking the extension itself.
  //
  // Note that 'version' here means something different than the version field
  // in the extension's manifest. We use the version as reported by the
  // background page to test how overinstalling crx files with the same
  // manifest version works.
  bool IsExtensionAtVersion(Extension* extension,
                            const std::string& expected_version) {
    // Test that the extension's version from the manifest and reported by the
    // background page is correct.  This is to ensure that the processes are in
    // sync with the Extension.
    ExtensionProcessManager* manager = browser()->profile()->
        GetExtensionProcessManager();
    ExtensionHost* ext_host = manager->GetBackgroundHostForExtension(extension);
    EXPECT_TRUE(ext_host);
    if (!ext_host)
      return false;

    std::string version_from_bg;
    bool exec = ui_test_utils::ExecuteJavaScriptAndExtractString(
        ext_host->render_view_host(), L"", L"version()", &version_from_bg);
    EXPECT_TRUE(exec);
    if (!exec)
      return false;

    if (version_from_bg != expected_version ||
        extension->VersionString() != expected_version)
      return false;
    return true;
  }

  // Helper method that installs a low permission extension then updates
  // to the second version requiring increased permissions. Returns whether
  // the operation was completed successfully.
  bool InstallAndUpdateIncreasingPermissionsExtension() {
    ExtensionsService* service = browser()->profile()->GetExtensionsService();
    size_t size_before = service->extensions()->size();

    // Install the initial version, which should happen just fine.
    if (!InstallExtension(
        test_data_dir_.AppendASCII("permissions-low-v1.crx"), 1))
      return false;

    // Upgrade to a version that wants more permissions. We should disable the
    // extension and prompt the user to reenable.
    if (service->extensions()->size() != size_before + 1)
      return false;
    if (!UpdateExtension(
        service->extensions()->at(size_before)->id(),
        test_data_dir_.AppendASCII("permissions-high-v2.crx"), -1))
      return false;
    EXPECT_EQ(size_before, service->extensions()->size());
    if (service->disabled_extensions()->size() != 1u)
      return false;
    return true;
  }
};

// Tests that installing the same version overwrites.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallSameVersion) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));
  FilePath old_path = service->extensions()->back()->path();

  // Install an extension with the same version. The previous install should be
  // overwritten.
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install_same_version.crx"), 0));
  FilePath new_path = service->extensions()->back()->path();

  EXPECT_FALSE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                    "1.0"));
  EXPECT_NE(old_path.value(), new_path.value());
}

IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallOlderVersion) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install_older_version.crx"), 0));
  EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                   "1.0"));
}

IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallThenCancel) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));

  // Cancel this install.
  StartInstallButCancel(test_data_dir_.AppendASCII("install/install_v2.crx"));
  EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                   "1.0"));
}

// Tests that installing and uninstalling extensions don't crash with an
// incognito window open.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, Incognito) {
  // Open an incognito window to the extensions management page.  We just
  // want to make sure that we don't crash while playing with extensions when
  // this guy is around.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
                                     GURL(chrome::kChromeUIExtensionsURL));

  ASSERT_TRUE(InstallExtension(test_data_dir_.AppendASCII("good.crx"), 1));
  UninstallExtension("ldnnhddmnhbkjipkidpdiheffobcpfmf");
}

#if defined(OS_LINUX)
// See http://crbug.com/32906 and http://crbug.com/36890
#define MAYBE_UpdatePermissions DISABLED_UpdatePermissions
#else
#define MAYBE_UpdatePermissions UpdatePermissions
#endif

// Tests the process of updating an extension to one that requires higher
// permissions.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_UpdatePermissions) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension());
  const size_t size_before = service->extensions()->size();

  // Now try reenabling it.
  service->EnableExtension(service->disabled_extensions()->at(0)->id());
  EXPECT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
}

// Tests that we can uninstall a disabled extension.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, UninstallDisabled) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension());
  const size_t size_before = service->extensions()->size();

  // Now try uninstalling it.
  UninstallExtension(service->disabled_extensions()->at(0)->id());
  EXPECT_EQ(size_before, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
}

// Tests that disabling and re-enabling an extension works.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, DisableEnable) {
  ExtensionProcessManager* manager = browser()->profile()->
      GetExtensionProcessManager();
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();

  // Load an extension, expect the background page to be available.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
                    .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
                    .AppendASCII("1.0")));
  ASSERT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
  Extension* extension = service->extensions()->at(size_before);
  EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());

  // After disabling, the background page should go away.
  service->DisableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa");
  EXPECT_EQ(size_before, service->extensions()->size());
  EXPECT_EQ(1u, service->disabled_extensions()->size());
  EXPECT_FALSE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());

  // And bring it back.
  service->EnableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa");
  EXPECT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
  EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());
}

// Tests extension autoupdate.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, AutoUpdate) {
  FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
  // Note: This interceptor gets requests on the IO thread.
  scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor());
  URLFetcher::enable_interception_for_tests(true);

  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest",
                                     basedir.AppendASCII("manifest_v2.xml"));
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx",
                                     basedir.AppendASCII("v2.crx"));

  // Install version 1 of the extension.
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(service->disabled_extensions()->empty());
  ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v1.crx"), 1));
  const ExtensionList* extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_TRUE(service->HasInstalledExtensions());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("1.0", extensions->at(size_before)->VersionString());

  // We don't want autoupdate blacklist checks.
  service->updater()->set_blacklist_checks_enabled(false);

  // Run autoupdate and make sure version 2 of the extension was installed.
  service->updater()->CheckNow();
  ASSERT_TRUE(WaitForExtensionInstall());
  extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("2.0", extensions->at(size_before)->VersionString());

  // Now try doing an update to version 3, which has been incorrectly
  // signed. This should fail.
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest",
                                     basedir.AppendASCII("manifest_v3.xml"));
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v3.crx",
                                     basedir.AppendASCII("v3.crx"));

  service->updater()->CheckNow();
  ASSERT_TRUE(WaitForExtensionInstallError());

  // Make sure the extension state is the same as before.
  extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("2.0", extensions->at(size_before)->VersionString());
}
<commit_msg>Marking the test as flaky since it fails 14% of the time.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/ref_counted.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/extensions/autoupdate_interceptor.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/extension_updater.h"
#include "chrome/browser/profile.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"

class ExtensionManagementTest : public ExtensionBrowserTest {
 protected:
  // Helper method that returns whether the extension is at the given version.
  // This calls version(), which must be defined in the extension's bg page,
  // as well as asking the extension itself.
  //
  // Note that 'version' here means something different than the version field
  // in the extension's manifest. We use the version as reported by the
  // background page to test how overinstalling crx files with the same
  // manifest version works.
  bool IsExtensionAtVersion(Extension* extension,
                            const std::string& expected_version) {
    // Test that the extension's version from the manifest and reported by the
    // background page is correct.  This is to ensure that the processes are in
    // sync with the Extension.
    ExtensionProcessManager* manager = browser()->profile()->
        GetExtensionProcessManager();
    ExtensionHost* ext_host = manager->GetBackgroundHostForExtension(extension);
    EXPECT_TRUE(ext_host);
    if (!ext_host)
      return false;

    std::string version_from_bg;
    bool exec = ui_test_utils::ExecuteJavaScriptAndExtractString(
        ext_host->render_view_host(), L"", L"version()", &version_from_bg);
    EXPECT_TRUE(exec);
    if (!exec)
      return false;

    if (version_from_bg != expected_version ||
        extension->VersionString() != expected_version)
      return false;
    return true;
  }

  // Helper method that installs a low permission extension then updates
  // to the second version requiring increased permissions. Returns whether
  // the operation was completed successfully.
  bool InstallAndUpdateIncreasingPermissionsExtension() {
    ExtensionsService* service = browser()->profile()->GetExtensionsService();
    size_t size_before = service->extensions()->size();

    // Install the initial version, which should happen just fine.
    if (!InstallExtension(
        test_data_dir_.AppendASCII("permissions-low-v1.crx"), 1))
      return false;

    // Upgrade to a version that wants more permissions. We should disable the
    // extension and prompt the user to reenable.
    if (service->extensions()->size() != size_before + 1)
      return false;
    if (!UpdateExtension(
        service->extensions()->at(size_before)->id(),
        test_data_dir_.AppendASCII("permissions-high-v2.crx"), -1))
      return false;
    EXPECT_EQ(size_before, service->extensions()->size());
    if (service->disabled_extensions()->size() != 1u)
      return false;
    return true;
  }
};

// Tests that installing the same version overwrites.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallSameVersion) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));
  FilePath old_path = service->extensions()->back()->path();

  // Install an extension with the same version. The previous install should be
  // overwritten.
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install_same_version.crx"), 0));
  FilePath new_path = service->extensions()->back()->path();

  EXPECT_FALSE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                    "1.0"));
  EXPECT_NE(old_path.value(), new_path.value());
}

IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallOlderVersion) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install_older_version.crx"), 0));
  EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                   "1.0"));
}

IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallThenCancel) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(InstallExtension(
      test_data_dir_.AppendASCII("install/install.crx"), 1));

  // Cancel this install.
  StartInstallButCancel(test_data_dir_.AppendASCII("install/install_v2.crx"));
  EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before),
                                   "1.0"));
}

#if defined(OS_MACOSX)
// See http://crbug.com/46097
#define MAYBE_Incognito FLAKY_Incognito
#else
#define MAYBE_Incognito Incognito
#endif
// Tests that installing and uninstalling extensions don't crash with an
// incognito window open.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_Incognito) {
  // Open an incognito window to the extensions management page.  We just
  // want to make sure that we don't crash while playing with extensions when
  // this guy is around.
  ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
                                     GURL(chrome::kChromeUIExtensionsURL));

  ASSERT_TRUE(InstallExtension(test_data_dir_.AppendASCII("good.crx"), 1));
  UninstallExtension("ldnnhddmnhbkjipkidpdiheffobcpfmf");
}

#if defined(OS_LINUX)
// See http://crbug.com/32906 and http://crbug.com/36890
#define MAYBE_UpdatePermissions DISABLED_UpdatePermissions
#else
#define MAYBE_UpdatePermissions UpdatePermissions
#endif

// Tests the process of updating an extension to one that requires higher
// permissions.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_UpdatePermissions) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension());
  const size_t size_before = service->extensions()->size();

  // Now try reenabling it.
  service->EnableExtension(service->disabled_extensions()->at(0)->id());
  EXPECT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
}

// Tests that we can uninstall a disabled extension.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, UninstallDisabled) {
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension());
  const size_t size_before = service->extensions()->size();

  // Now try uninstalling it.
  UninstallExtension(service->disabled_extensions()->at(0)->id());
  EXPECT_EQ(size_before, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
}

// Tests that disabling and re-enabling an extension works.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, DisableEnable) {
  ExtensionProcessManager* manager = browser()->profile()->
      GetExtensionProcessManager();
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();

  // Load an extension, expect the background page to be available.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
                    .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
                    .AppendASCII("1.0")));
  ASSERT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
  Extension* extension = service->extensions()->at(size_before);
  EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());

  // After disabling, the background page should go away.
  service->DisableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa");
  EXPECT_EQ(size_before, service->extensions()->size());
  EXPECT_EQ(1u, service->disabled_extensions()->size());
  EXPECT_FALSE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());

  // And bring it back.
  service->EnableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa");
  EXPECT_EQ(size_before + 1, service->extensions()->size());
  EXPECT_EQ(0u, service->disabled_extensions()->size());
  EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension));
  ASSERT_TRUE(service->HasInstalledExtensions());
}

// Tests extension autoupdate.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, AutoUpdate) {
  FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
  // Note: This interceptor gets requests on the IO thread.
  scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor());
  URLFetcher::enable_interception_for_tests(true);

  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest",
                                     basedir.AppendASCII("manifest_v2.xml"));
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx",
                                     basedir.AppendASCII("v2.crx"));

  // Install version 1 of the extension.
  ExtensionsService* service = browser()->profile()->GetExtensionsService();
  const size_t size_before = service->extensions()->size();
  ASSERT_TRUE(service->disabled_extensions()->empty());
  ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v1.crx"), 1));
  const ExtensionList* extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_TRUE(service->HasInstalledExtensions());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("1.0", extensions->at(size_before)->VersionString());

  // We don't want autoupdate blacklist checks.
  service->updater()->set_blacklist_checks_enabled(false);

  // Run autoupdate and make sure version 2 of the extension was installed.
  service->updater()->CheckNow();
  ASSERT_TRUE(WaitForExtensionInstall());
  extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("2.0", extensions->at(size_before)->VersionString());

  // Now try doing an update to version 3, which has been incorrectly
  // signed. This should fail.
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest",
                                     basedir.AppendASCII("manifest_v3.xml"));
  interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v3.crx",
                                     basedir.AppendASCII("v3.crx"));

  service->updater()->CheckNow();
  ASSERT_TRUE(WaitForExtensionInstallError());

  // Make sure the extension state is the same as before.
  extensions = service->extensions();
  ASSERT_EQ(size_before + 1, extensions->size());
  ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf",
            extensions->at(size_before)->id());
  ASSERT_EQ("2.0", extensions->at(size_before)->VersionString());
}
<|endoftext|>


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

#include "chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h"

#include <string>

#include "app/l10n_util.h"
#include "base/environment.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_resource.h"
#include "gfx/gtk_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// Size (in pixels) of the icon preview.
const int kIconPreviewSizePixels = 32;

// Height (in lines) of the shortcut description label.
const int kDescriptionLabelHeightLines = 3;

}  // namespace

// static
void CreateWebApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
                                                  TabContents* tab_contents) {
  new CreateWebApplicationShortcutsDialogGtk(parent, tab_contents);
}

void CreateChromeApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
                                                     const Extension* app) {
  new CreateChromeApplicationShortcutsDialogGtk(parent, app);
}

CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk(
    GtkWindow* parent)
  : parent_(parent),
    error_dialog_(NULL) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Will be balanced by Release later.
  AddRef();
}

void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf(
    const SkBitmap& bitmap) {
  // Prepare the icon. Try to scale it if it's too small, otherwise it would
  // look weird.
  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon);
  int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
  int pixbuf_height = gdk_pixbuf_get_height(pixbuf);
  if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) {
    // Only scale the pixbuf if it's a square (for simplicity).
    // Generally it should be square, if it's a favicon or app icon.
    // Use the highest quality interpolation. The scaling is
    // going to have low quality anyway, because the initial image
    // is likely small.
    favicon_pixbuf_ = gdk_pixbuf_scale_simple(pixbuf,
                                              kIconPreviewSizePixels,
                                              kIconPreviewSizePixels,
                                              GDK_INTERP_HYPER);
    g_object_unref(pixbuf);
  } else {
    favicon_pixbuf_ = pixbuf;
  }
}

void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) {
  // Build the dialog.
  create_dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(),
      parent,
      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_CANCEL,
      GTK_RESPONSE_REJECT,
      NULL);
  gtk_widget_realize(create_dialog_);
  gtk_util::SetWindowSizeFromResources(GTK_WINDOW(create_dialog_),
                                       IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS,
                                       -1,  // height
                                       false);  // resizable
  gtk_util::AddButtonToDialog(create_dialog_,
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_COMMIT).c_str(),
      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);

  GtkWidget* content_area = GTK_DIALOG(create_dialog_)->vbox;
  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(content_area), vbox);

  // Create a box containing basic information about the new shortcut: an image
  // on the left, and a description on the right.
  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox),
                                 gtk_util::kControlSpacing);

  // Put the icon preview in place.
  GtkWidget* favicon_image = gtk_image_new_from_pixbuf(favicon_pixbuf_);
  gtk_box_pack_start(GTK_BOX(hbox), favicon_image, FALSE, FALSE, 0);

  // Create the label with application shortcut description.
  GtkWidget* description_label = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(hbox), description_label, FALSE, FALSE, 0);
  gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
  gtk_widget_realize(description_label);
  int label_height;
  gtk_util::GetWidgetSizeFromCharacters(description_label, -1,
                                        kDescriptionLabelHeightLines, NULL,
                                        &label_height);
  gtk_widget_set_size_request(description_label, -1, label_height);
  gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
  std::string description(UTF16ToUTF8(shortcut_info_.description));
  std::string title(UTF16ToUTF8(shortcut_info_.title));
  gtk_label_set_text(GTK_LABEL(description_label),
                     (description.empty() ? title : description).c_str());

  // Label on top of the checkboxes.
  GtkWidget* checkboxes_label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_LABEL).c_str());
  gtk_misc_set_alignment(GTK_MISC(checkboxes_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), checkboxes_label, FALSE, FALSE, 0);

  // Desktop checkbox.
  desktop_checkbox_ = gtk_check_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX).c_str());
  gtk_box_pack_start(GTK_BOX(vbox), desktop_checkbox_, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(desktop_checkbox_), true);
  g_signal_connect(desktop_checkbox_, "toggled",
                   G_CALLBACK(OnToggleCheckboxThunk), this);

  // Menu checkbox.
  menu_checkbox_ = gtk_check_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_MENU_CHKBOX).c_str());
  gtk_box_pack_start(GTK_BOX(vbox), menu_checkbox_, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_checkbox_), false);
  g_signal_connect(menu_checkbox_, "toggled",
                   G_CALLBACK(OnToggleCheckboxThunk), this);

  g_signal_connect(create_dialog_, "response",
                   G_CALLBACK(OnCreateDialogResponseThunk), this);
  gtk_widget_show_all(create_dialog_);
}

CreateApplicationShortcutsDialogGtk::~CreateApplicationShortcutsDialogGtk() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  gtk_widget_destroy(create_dialog_);

  if (error_dialog_)
    gtk_widget_destroy(error_dialog_);

  g_object_unref(favicon_pixbuf_);
}

void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse(
    GtkWidget* widget, int response) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (response == GTK_RESPONSE_ACCEPT) {
    shortcut_info_.create_on_desktop =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_));
    shortcut_info_.create_in_applications_menu =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_));
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
         NewRunnableMethod(this,
             &CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut,
             shortcut_info_));

    OnCreatedShortcut();
  } else {
    Release();
  }
}

void CreateApplicationShortcutsDialogGtk::OnErrorDialogResponse(
    GtkWidget* widget, int response) {
  Release();
}

void CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut(
    const ShellIntegration::ShortcutInfo& shortcut_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  scoped_ptr<base::Environment> env(base::Environment::Create());

  std::string shortcut_template;
  if (ShellIntegration::GetDesktopShortcutTemplate(env.get(),
                                                   &shortcut_template)) {
    ShellIntegration::CreateDesktopShortcut(shortcut_info,
                                            shortcut_template);
    Release();
  } else {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        NewRunnableMethod(this,
            &CreateApplicationShortcutsDialogGtk::ShowErrorDialog));
  }
}

void CreateApplicationShortcutsDialogGtk::ShowErrorDialog() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Hide the create dialog so that the user can no longer interact with it.
  gtk_widget_hide(create_dialog_);

  error_dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_TITLE).c_str(),
      NULL,
      (GtkDialogFlags) (GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_OK,
      GTK_RESPONSE_ACCEPT,
      NULL);
  gtk_widget_realize(error_dialog_);
  gtk_util::SetWindowSizeFromResources(
      GTK_WINDOW(error_dialog_),
      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_WIDTH_CHARS,
      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_HEIGHT_LINES,
      false);  // resizable
  GtkWidget* content_area = GTK_DIALOG(error_dialog_)->vbox;
  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(content_area), vbox);

  // Label on top of the checkboxes.
  GtkWidget* description = gtk_label_new(
      l10n_util::GetStringFUTF8(
          IDS_CREATE_SHORTCUTS_ERROR_LABEL,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
  gtk_label_set_line_wrap(GTK_LABEL(description), TRUE);
  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);

  g_signal_connect(error_dialog_, "response",
                   G_CALLBACK(OnErrorDialogResponseThunk), this);
  gtk_widget_show_all(error_dialog_);
}

void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) {
  gboolean can_accept = FALSE;

  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)) ||
      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) {
    can_accept = TRUE;
  }

  gtk_dialog_set_response_sensitive(GTK_DIALOG(create_dialog_),
                                    GTK_RESPONSE_ACCEPT,
                                    can_accept);
}

CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk(
    GtkWindow* parent,
    TabContents* tab_contents)
  : CreateApplicationShortcutsDialogGtk(parent),
    tab_contents_(tab_contents) {

  // Get shortcut information now, it's needed for our UI.
  web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_);
  CreateIconPixBuf(shortcut_info_.favicon);

  CreateDialogBox(parent);
}

void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() {
  if (tab_contents_->delegate())
    tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_);
}

CreateChromeApplicationShortcutsDialogGtk::
    CreateChromeApplicationShortcutsDialogGtk(
        GtkWindow* parent,
        const Extension* app)
      : CreateApplicationShortcutsDialogGtk(parent),
        app_(app),
        ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))  {

  // Get shortcut information now, it's needed for our UI.
  shortcut_info_.extension_id = UTF8ToUTF16(app_->id());
  shortcut_info_.url = GURL(app_->launch_web_url());
  shortcut_info_.title = UTF8ToUTF16(app_->name());
  shortcut_info_.description = UTF8ToUTF16(app_->description());

  // Get the icon.
  const gfx::Size max_size(kIconPreviewSizePixels, kIconPreviewSizePixels);
  ExtensionResource icon_resource = app_->GetIconResource(
      kIconPreviewSizePixels, ExtensionIconSet::MATCH_BIGGER);

  // If no icon exists that is the desired size or larger, get the
  // largest icon available:
  if (icon_resource.empty())
    icon_resource = app_->GetIconResource(
        kIconPreviewSizePixels, ExtensionIconSet::MATCH_SMALLER);

  tracker_.LoadImage(app_,
                     icon_resource,
                     max_size,
                     ImageLoadingTracker::DONT_CACHE);
}

// Called by tracker_ when the app's icon is loaded.
void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image->isNull()) {
    NOTREACHED() << "Corrupt image in profile?";
    return;
  }
  shortcut_info_.favicon = *image;

  CreateIconPixBuf(*image);
  CreateDialogBox(parent_);
}
<commit_msg>[gtk] fix line wrap issue on app shortcut dialog<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h"

#include <string>

#include "app/l10n_util.h"
#include "base/environment.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_resource.h"
#include "gfx/gtk_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// Size (in pixels) of the icon preview.
const int kIconPreviewSizePixels = 32;

// Height (in lines) of the shortcut description label.
const int kDescriptionLabelHeightLines = 3;

}  // namespace

// static
void CreateWebApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
                                                  TabContents* tab_contents) {
  new CreateWebApplicationShortcutsDialogGtk(parent, tab_contents);
}

void CreateChromeApplicationShortcutsDialogGtk::Show(GtkWindow* parent,
                                                     const Extension* app) {
  new CreateChromeApplicationShortcutsDialogGtk(parent, app);
}

CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk(
    GtkWindow* parent)
  : parent_(parent),
    error_dialog_(NULL) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Will be balanced by Release later.
  AddRef();
}

void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf(
    const SkBitmap& bitmap) {
  // Prepare the icon. Try to scale it if it's too small, otherwise it would
  // look weird.
  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon);
  int pixbuf_width = gdk_pixbuf_get_width(pixbuf);
  int pixbuf_height = gdk_pixbuf_get_height(pixbuf);
  if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) {
    // Only scale the pixbuf if it's a square (for simplicity).
    // Generally it should be square, if it's a favicon or app icon.
    // Use the highest quality interpolation. The scaling is
    // going to have low quality anyway, because the initial image
    // is likely small.
    favicon_pixbuf_ = gdk_pixbuf_scale_simple(pixbuf,
                                              kIconPreviewSizePixels,
                                              kIconPreviewSizePixels,
                                              GDK_INTERP_HYPER);
    g_object_unref(pixbuf);
  } else {
    favicon_pixbuf_ = pixbuf;
  }
}

void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) {
  // Build the dialog.
  create_dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(),
      parent,
      (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_CANCEL,
      GTK_RESPONSE_REJECT,
      NULL);
  gtk_widget_realize(create_dialog_);
  gtk_window_set_resizable(GTK_WINDOW(create_dialog_), false);
  gtk_util::AddButtonToDialog(create_dialog_,
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_COMMIT).c_str(),
      GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT);

  GtkWidget* content_area = GTK_DIALOG(create_dialog_)->vbox;
  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(content_area), vbox);

  // Create a box containing basic information about the new shortcut: an image
  // on the left, and a description on the right.
  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox),
                                 gtk_util::kControlSpacing);

  // Put the icon preview in place.
  GtkWidget* favicon_image = gtk_image_new_from_pixbuf(favicon_pixbuf_);
  gtk_box_pack_start(GTK_BOX(hbox), favicon_image, FALSE, FALSE, 0);

  // Create the label with application shortcut description.
  GtkWidget* description_label = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(hbox), description_label, FALSE, FALSE, 0);
  gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
  gtk_widget_realize(description_label);

  // Set the size request on the label so it knows where to line wrap. The width
  // is the desired size of the dialog less the space reserved for padding and
  // the image.
  int label_width, label_height;
  gtk_util::GetWidgetSizeFromResources(
      description_label,
      IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS, -1, &label_width, NULL);
  label_width -= gtk_util::kControlSpacing * 3 +
      gdk_pixbuf_get_width(favicon_pixbuf_);
  gtk_util::GetWidgetSizeFromCharacters(
      description_label, -1, kDescriptionLabelHeightLines, NULL, &label_height);
  gtk_widget_set_size_request(description_label, label_width, label_height);
  gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
  std::string description(UTF16ToUTF8(shortcut_info_.description));
  std::string title(UTF16ToUTF8(shortcut_info_.title));
  gtk_label_set_text(GTK_LABEL(description_label),
                     (description.empty() ? title : description).c_str());

  // Label on top of the checkboxes.
  GtkWidget* checkboxes_label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_LABEL).c_str());
  gtk_misc_set_alignment(GTK_MISC(checkboxes_label), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), checkboxes_label, FALSE, FALSE, 0);

  // Desktop checkbox.
  desktop_checkbox_ = gtk_check_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX).c_str());
  gtk_box_pack_start(GTK_BOX(vbox), desktop_checkbox_, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(desktop_checkbox_), true);
  g_signal_connect(desktop_checkbox_, "toggled",
                   G_CALLBACK(OnToggleCheckboxThunk), this);

  // Menu checkbox.
  menu_checkbox_ = gtk_check_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_MENU_CHKBOX).c_str());
  gtk_box_pack_start(GTK_BOX(vbox), menu_checkbox_, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_checkbox_), false);
  g_signal_connect(menu_checkbox_, "toggled",
                   G_CALLBACK(OnToggleCheckboxThunk), this);

  g_signal_connect(create_dialog_, "response",
                   G_CALLBACK(OnCreateDialogResponseThunk), this);
  gtk_widget_show_all(create_dialog_);
}

CreateApplicationShortcutsDialogGtk::~CreateApplicationShortcutsDialogGtk() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  gtk_widget_destroy(create_dialog_);

  if (error_dialog_)
    gtk_widget_destroy(error_dialog_);

  g_object_unref(favicon_pixbuf_);
}

void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse(
    GtkWidget* widget, int response) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (response == GTK_RESPONSE_ACCEPT) {
    shortcut_info_.create_on_desktop =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_));
    shortcut_info_.create_in_applications_menu =
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_));
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
         NewRunnableMethod(this,
             &CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut,
             shortcut_info_));

    OnCreatedShortcut();
  } else {
    Release();
  }
}

void CreateApplicationShortcutsDialogGtk::OnErrorDialogResponse(
    GtkWidget* widget, int response) {
  Release();
}

void CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut(
    const ShellIntegration::ShortcutInfo& shortcut_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  scoped_ptr<base::Environment> env(base::Environment::Create());

  std::string shortcut_template;
  if (ShellIntegration::GetDesktopShortcutTemplate(env.get(),
                                                   &shortcut_template)) {
    ShellIntegration::CreateDesktopShortcut(shortcut_info,
                                            shortcut_template);
    Release();
  } else {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        NewRunnableMethod(this,
            &CreateApplicationShortcutsDialogGtk::ShowErrorDialog));
  }
}

void CreateApplicationShortcutsDialogGtk::ShowErrorDialog() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Hide the create dialog so that the user can no longer interact with it.
  gtk_widget_hide(create_dialog_);

  error_dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_TITLE).c_str(),
      NULL,
      (GtkDialogFlags) (GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_OK,
      GTK_RESPONSE_ACCEPT,
      NULL);
  gtk_widget_realize(error_dialog_);
  gtk_util::SetWindowSizeFromResources(
      GTK_WINDOW(error_dialog_),
      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_WIDTH_CHARS,
      IDS_CREATE_SHORTCUTS_ERROR_DIALOG_HEIGHT_LINES,
      false);  // resizable
  GtkWidget* content_area = GTK_DIALOG(error_dialog_)->vbox;
  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(content_area), vbox);

  // Label on top of the checkboxes.
  GtkWidget* description = gtk_label_new(
      l10n_util::GetStringFUTF8(
          IDS_CREATE_SHORTCUTS_ERROR_LABEL,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
  gtk_label_set_line_wrap(GTK_LABEL(description), TRUE);
  gtk_misc_set_alignment(GTK_MISC(description), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0);

  g_signal_connect(error_dialog_, "response",
                   G_CALLBACK(OnErrorDialogResponseThunk), this);
  gtk_widget_show_all(error_dialog_);
}

void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) {
  gboolean can_accept = FALSE;

  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)) ||
      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) {
    can_accept = TRUE;
  }

  gtk_dialog_set_response_sensitive(GTK_DIALOG(create_dialog_),
                                    GTK_RESPONSE_ACCEPT,
                                    can_accept);
}

CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk(
    GtkWindow* parent,
    TabContents* tab_contents)
  : CreateApplicationShortcutsDialogGtk(parent),
    tab_contents_(tab_contents) {

  // Get shortcut information now, it's needed for our UI.
  web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_);
  CreateIconPixBuf(shortcut_info_.favicon);

  CreateDialogBox(parent);
}

void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() {
  if (tab_contents_->delegate())
    tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_);
}

CreateChromeApplicationShortcutsDialogGtk::
    CreateChromeApplicationShortcutsDialogGtk(
        GtkWindow* parent,
        const Extension* app)
      : CreateApplicationShortcutsDialogGtk(parent),
        app_(app),
        ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this))  {

  // Get shortcut information now, it's needed for our UI.
  shortcut_info_.extension_id = UTF8ToUTF16(app_->id());
  shortcut_info_.url = GURL(app_->launch_web_url());
  shortcut_info_.title = UTF8ToUTF16(app_->name());
  shortcut_info_.description = UTF8ToUTF16(app_->description());

  // Get the icon.
  const gfx::Size max_size(kIconPreviewSizePixels, kIconPreviewSizePixels);
  ExtensionResource icon_resource = app_->GetIconResource(
      kIconPreviewSizePixels, ExtensionIconSet::MATCH_BIGGER);

  // If no icon exists that is the desired size or larger, get the
  // largest icon available:
  if (icon_resource.empty())
    icon_resource = app_->GetIconResource(
        kIconPreviewSizePixels, ExtensionIconSet::MATCH_SMALLER);

  tracker_.LoadImage(app_,
                     icon_resource,
                     max_size,
                     ImageLoadingTracker::DONT_CACHE);
}

// Called by tracker_ when the app's icon is loaded.
void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image->isNull()) {
    NOTREACHED() << "Corrupt image in profile?";
    return;
  }
  shortcut_info_.favicon = *image;

  CreateIconPixBuf(*image);
  CreateDialogBox(parent_);
}
<|endoftext|>


<commit_before>#include "dynet/lstm.h"

#include <fstream>
#include <string>
#include <cassert>
#include <vector>
#include <iostream>

#include <boost/serialization/utility.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include "dynet/nodes.h"
#include "dynet/io-macros.h"

using namespace std;
using namespace dynet::expr;

namespace dynet {

enum { X2I, H2I, C2I, BI, X2O, H2O, C2O, BO, X2C, H2C, BC };
enum { IA, IO, IW, HA, HO, HW, CA, CO, CW }; // Gal dropout masks

LSTMBuilder::LSTMBuilder(unsigned layers,
                         unsigned input_dim,
                         unsigned hidden_dim,
                         Model* model) : layers(layers), input_dim(input_dim), hidden_dim(hidden_dim) {
  unsigned layer_input_dim = input_dim;
  for (unsigned i = 0; i < layers; ++i) {
    // i
    Parameter p_x2i = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2i = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_c2i = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bi = model->add_parameters({hidden_dim});

    // o
    Parameter p_x2o = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2o = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_c2o = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bo = model->add_parameters({hidden_dim});

    // c
    Parameter p_x2c = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2c = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bc = model->add_parameters({hidden_dim});
    layer_input_dim = hidden_dim;  // output (hidden) from 1st layer is input to next

    vector<Parameter> ps = {p_x2i, p_h2i, p_c2i, p_bi, p_x2o, p_h2o, p_c2o, p_bo, p_x2c, p_h2c, p_bc};
    params.push_back(ps);
  }  // layers
  dropout_rate = 0.f;
}

void LSTMBuilder::new_graph_impl(ComputationGraph& cg) {
    _cg = &cg;
  param_vars.clear();

  for (unsigned i = 0; i < layers; ++i) {
    auto& p = params[i];

    //i
    Expression i_x2i = parameter(cg, p[X2I]);
    Expression i_h2i = parameter(cg, p[H2I]);
    Expression i_c2i = parameter(cg, p[C2I]);
    Expression i_bi = parameter(cg, p[BI]);
    //o
    Expression i_x2o = parameter(cg, p[X2O]);
    Expression i_h2o = parameter(cg, p[H2O]);
    Expression i_c2o = parameter(cg, p[C2O]);
    Expression i_bo = parameter(cg, p[BO]);
    //c
    Expression i_x2c = parameter(cg, p[X2C]);
    Expression i_h2c = parameter(cg, p[H2C]);
    Expression i_bc = parameter(cg, p[BC]);

    vector<Expression> vars = {i_x2i, i_h2i, i_c2i, i_bi, i_x2o, i_h2o, i_c2o, i_bo, i_x2c, i_h2c, i_bc};
    param_vars.push_back(vars);
  }
}

// layout: 0..layers = c
//         layers+1..2*layers = h
void LSTMBuilder::start_new_sequence_impl(const vector<Expression>& hinit) {
  h.clear();
  c.clear();
  // Init Gal Dropout masks for each layer
  masks.clear();
  for (unsigned i = 0; i < layers; ++i) {
    std::vector<Expression> masks_i;
    unsigned idim = (i == 0) ? input_dim : hidden_dim;
    if (dropout_rate > 0.f) {
      float retention_rate = 1.f - dropout_rate;
      float scale = 1.f / retention_rate;
      // in
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate) * scale);
      // h
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      // c
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate) * scale);
      masks.push_back(masks_i);
    }
  }
  if (hinit.size() > 0) {
    assert(layers * 2 == hinit.size());
    h0.resize(layers);
    c0.resize(layers);
    for (unsigned i = 0; i < layers; ++i) {
      c0[i] = hinit[i];
      h0[i] = hinit[i + layers];
    }
    has_initial_state = true;
  } else {
    has_initial_state = false;
  }
}

// TO DO - Make this correct
// Copied c from the previous step (otherwise c.size()< h.size())
// Also is creating a new step something we want?
// wouldn't overwriting the current one be better?
Expression LSTMBuilder::set_h_impl(int prev, const vector<Expression>& h_new) {
  if (h_new.size()) { assert(h_new.size() == layers); }
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression h_i = h_new[i];
    Expression c_i = c[t - 1][i];
    h[t][i] = h_i;
    c[t][i] = c_i;
  }
  return h[t].back();
}
// Current implementation : s_new is either {new_c[0],...,new_c[n]}
// or {new_c[0],...,new_c[n],new_h[0],...,new_h[n]}
Expression LSTMBuilder::set_s_impl(int prev, const std::vector<Expression>& s_new) {
  if (s_new.size()) { assert(s_new.size() == layers || s_new.size() == 2 * layers ); }
  bool only_c = s_new.size() == layers;
  const unsigned t = c.size();
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression h_i = only_c ? h[t - 1][i] : s_new[i + layers];
    Expression c_i = s_new[i];
    h[t][i] = h_i;
    c[t][i] = c_i;
  }
  return h[t].back();
}

Expression LSTMBuilder::add_input_impl(int prev, const Expression& x) {
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  vector<Expression>& ht = h.back();
  vector<Expression>& ct = c.back();
  Expression in = x;
  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];
    const vector<Expression>& masks_i = masks[i];
    Expression i_h_tm1, i_c_tm1;
    bool has_prev_state = (prev >= 0 || has_initial_state);
    if (prev < 0) {
      if (has_initial_state) {
        // intial value for h and c at timestep 0 in layer i
        // defaults to zero matrix input if not set in add_parameter_edges
        i_h_tm1 = h0[i];
        i_c_tm1 = c0[i];
      }
    } else {  // t > 0
      i_h_tm1 = h[prev][i];
      i_c_tm1 = c[prev][i];
    }
    // apply dropout according to https://arxiv.org/abs/1512.05287
    // input
    Expression i_ait;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_ait = affine_transform({vars[BI], vars[X2I], cmult(in, masks_i[IA]) , vars[H2I], cmult(i_h_tm1, masks_i[HA]), vars[C2I], cmult(i_c_tm1, masks_i[CA])});
      else
        i_ait = affine_transform({vars[BI], vars[X2I], in , vars[H2I], i_h_tm1, vars[C2I], i_c_tm1});
    else
      if (dropout_rate > 0.f)
        i_ait = affine_transform({vars[BI], vars[X2I], cmult(in, masks_i[IA])});
      else
        i_ait = affine_transform({vars[BI], vars[X2I], in});
    Expression i_it = logistic(i_ait);
    // forget
    Expression i_ft = 1.f - i_it;
    // write memory cell
    Expression i_awt;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_awt = affine_transform({vars[BC], vars[X2C], cmult(in, masks_i[IW]), vars[H2C], cmult(i_h_tm1, masks_i[HW])});
      else
        i_awt = affine_transform({vars[BC], vars[X2C], in, vars[H2C], i_h_tm1});
    else
      if (dropout_rate > 0.f)
        i_awt = affine_transform({vars[BC], vars[X2C], cmult(in, masks_i[IW])});
      else
        i_awt = affine_transform({vars[BC], vars[X2C], in});
    Expression i_wt = tanh(i_awt);
    // output
    if (has_prev_state) {
      Expression i_nwt = cmult(i_it, i_wt);
      Expression i_crt = cmult(i_ft, i_c_tm1);
      ct[i] = i_crt + i_nwt;
    } else {
      ct[i] = cmult(i_it, i_wt);
    }

    Expression i_aot;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_aot = affine_transform({vars[BO], vars[X2O], cmult(in, masks_i[IO]), vars[H2O], cmult(i_h_tm1, masks_i[HO]), vars[C2O], cmult(ct[i], masks_i[CO])});
      else
        i_aot = affine_transform({vars[BO], vars[X2O], in, vars[H2O], i_h_tm1, vars[C2O], ct[i]});
    else
      if (dropout_rate > 0.f)
        i_aot = affine_transform({vars[BO], vars[X2O], cmult(in, masks_i[IO]), vars[C2O], cmult(ct[i], masks_i[CO])});
      else
        i_aot = affine_transform({vars[BO], vars[X2O], in, vars[C2O], ct[i]});
    Expression i_ot = logistic(i_aot);
    Expression ph_t = tanh(ct[i]);
    in = ht[i] = cmult(i_ot, ph_t);
  }
  return ht.back();
}

void LSTMBuilder::copy(const RNNBuilder & rnn) {
  const LSTMBuilder & rnn_lstm = (const LSTMBuilder&)rnn;
  assert(params.size() == rnn_lstm.params.size());
  for (size_t i = 0; i < params.size(); ++i)
    for (size_t j = 0; j < params[i].size(); ++j)
      params[i][j] = rnn_lstm.params[i][j];
}

void LSTMBuilder::save_parameters_pretraining(const string& fname) const {
  cerr << "Writing LSTM parameters to " << fname << endl;
  ofstream of(fname);
  assert(of);
  boost::archive::binary_oarchive oa(of);
  std::string id = "LSTMBuilder:params";
  oa << id;
  oa << layers;
  for (unsigned i = 0; i < layers; ++i) {
    for (auto p : params[i]) {
      oa << p.get()->values;
    }
  }
}

void LSTMBuilder::load_parameters_pretraining(const string& fname) {
  cerr << "Loading LSTM parameters from " << fname << endl;
  ifstream of(fname);
  assert(of);
  boost::archive::binary_iarchive ia(of);
  std::string id;
  ia >> id;
  if (id != "LSTMBuilder:params") {
    cerr << "Bad id read\n";
    abort();
  }
  unsigned l = 0;
  ia >> l;
  if (l != layers) {
    cerr << "Bad number of layers\n";
    abort();
  }
  // TODO check other dimensions
  for (unsigned i = 0; i < layers; ++i) {
    for (auto p : params[i]) {
      ia >> p.get()->values;
    }
  }
}

template<class Archive>
void LSTMBuilder::serialize(Archive& ar, const unsigned int) {
  ar & boost::serialization::base_object<RNNBuilder>(*this);
  ar & params;
  ar & layers;
  ar & dropout_rate;
}
DYNET_SERIALIZE_IMPL(LSTMBuilder);

} // namespace dynet
<commit_msg>Removed extra multiply<commit_after>#include "dynet/lstm.h"

#include <fstream>
#include <string>
#include <cassert>
#include <vector>
#include <iostream>

#include <boost/serialization/utility.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include "dynet/nodes.h"
#include "dynet/io-macros.h"

using namespace std;
using namespace dynet::expr;

namespace dynet {

enum { X2I, H2I, C2I, BI, X2O, H2O, C2O, BO, X2C, H2C, BC };
enum { IA, IO, IW, HA, HO, HW, CA, CO, CW }; // Gal dropout masks

LSTMBuilder::LSTMBuilder(unsigned layers,
                         unsigned input_dim,
                         unsigned hidden_dim,
                         Model* model) : layers(layers), input_dim(input_dim), hidden_dim(hidden_dim) {
  unsigned layer_input_dim = input_dim;
  for (unsigned i = 0; i < layers; ++i) {
    // i
    Parameter p_x2i = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2i = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_c2i = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bi = model->add_parameters({hidden_dim});

    // o
    Parameter p_x2o = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2o = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_c2o = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bo = model->add_parameters({hidden_dim});

    // c
    Parameter p_x2c = model->add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2c = model->add_parameters({hidden_dim, hidden_dim});
    Parameter p_bc = model->add_parameters({hidden_dim});
    layer_input_dim = hidden_dim;  // output (hidden) from 1st layer is input to next

    vector<Parameter> ps = {p_x2i, p_h2i, p_c2i, p_bi, p_x2o, p_h2o, p_c2o, p_bo, p_x2c, p_h2c, p_bc};
    params.push_back(ps);
  }  // layers
  dropout_rate = 0.f;
}

void LSTMBuilder::new_graph_impl(ComputationGraph& cg) {
    _cg = &cg;
  param_vars.clear();

  for (unsigned i = 0; i < layers; ++i) {
    auto& p = params[i];

    //i
    Expression i_x2i = parameter(cg, p[X2I]);
    Expression i_h2i = parameter(cg, p[H2I]);
    Expression i_c2i = parameter(cg, p[C2I]);
    Expression i_bi = parameter(cg, p[BI]);
    //o
    Expression i_x2o = parameter(cg, p[X2O]);
    Expression i_h2o = parameter(cg, p[H2O]);
    Expression i_c2o = parameter(cg, p[C2O]);
    Expression i_bo = parameter(cg, p[BO]);
    //c
    Expression i_x2c = parameter(cg, p[X2C]);
    Expression i_h2c = parameter(cg, p[H2C]);
    Expression i_bc = parameter(cg, p[BC]);

    vector<Expression> vars = {i_x2i, i_h2i, i_c2i, i_bi, i_x2o, i_h2o, i_c2o, i_bo, i_x2c, i_h2c, i_bc};
    param_vars.push_back(vars);
  }
}

// layout: 0..layers = c
//         layers+1..2*layers = h
void LSTMBuilder::start_new_sequence_impl(const vector<Expression>& hinit) {
  h.clear();
  c.clear();
  // Init Gal Dropout masks for each layer
  masks.clear();
  for (unsigned i = 0; i < layers; ++i) {
    std::vector<Expression> masks_i;
    unsigned idim = (i == 0) ? input_dim : hidden_dim;
    if (dropout_rate > 0.f) {
      float retention_rate = 1.f - dropout_rate;
      float scale = 1.f / retention_rate;
      // in
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ idim}, retention_rate, scale));
      // h
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      // c
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      masks_i.push_back(random_bernoulli(*_cg,{ hidden_dim}, retention_rate, scale));
      masks.push_back(masks_i);
    }
  }
  if (hinit.size() > 0) {
    assert(layers * 2 == hinit.size());
    h0.resize(layers);
    c0.resize(layers);
    for (unsigned i = 0; i < layers; ++i) {
      c0[i] = hinit[i];
      h0[i] = hinit[i + layers];
    }
    has_initial_state = true;
  } else {
    has_initial_state = false;
  }
}

// TO DO - Make this correct
// Copied c from the previous step (otherwise c.size()< h.size())
// Also is creating a new step something we want?
// wouldn't overwriting the current one be better?
Expression LSTMBuilder::set_h_impl(int prev, const vector<Expression>& h_new) {
  if (h_new.size()) { assert(h_new.size() == layers); }
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression h_i = h_new[i];
    Expression c_i = c[t - 1][i];
    h[t][i] = h_i;
    c[t][i] = c_i;
  }
  return h[t].back();
}
// Current implementation : s_new is either {new_c[0],...,new_c[n]}
// or {new_c[0],...,new_c[n],new_h[0],...,new_h[n]}
Expression LSTMBuilder::set_s_impl(int prev, const std::vector<Expression>& s_new) {
  if (s_new.size()) { assert(s_new.size() == layers || s_new.size() == 2 * layers ); }
  bool only_c = s_new.size() == layers;
  const unsigned t = c.size();
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression h_i = only_c ? h[t - 1][i] : s_new[i + layers];
    Expression c_i = s_new[i];
    h[t][i] = h_i;
    c[t][i] = c_i;
  }
  return h[t].back();
}

Expression LSTMBuilder::add_input_impl(int prev, const Expression& x) {
  h.push_back(vector<Expression>(layers));
  c.push_back(vector<Expression>(layers));
  vector<Expression>& ht = h.back();
  vector<Expression>& ct = c.back();
  Expression in = x;
  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];
    const vector<Expression>& masks_i = masks[i];
    Expression i_h_tm1, i_c_tm1;
    bool has_prev_state = (prev >= 0 || has_initial_state);
    if (prev < 0) {
      if (has_initial_state) {
        // intial value for h and c at timestep 0 in layer i
        // defaults to zero matrix input if not set in add_parameter_edges
        i_h_tm1 = h0[i];
        i_c_tm1 = c0[i];
      }
    } else {  // t > 0
      i_h_tm1 = h[prev][i];
      i_c_tm1 = c[prev][i];
    }
    // apply dropout according to https://arxiv.org/abs/1512.05287
    // input
    Expression i_ait;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_ait = affine_transform({vars[BI], vars[X2I], cmult(in, masks_i[IA]) , vars[H2I], cmult(i_h_tm1, masks_i[HA]), vars[C2I], cmult(i_c_tm1, masks_i[CA])});
      else
        i_ait = affine_transform({vars[BI], vars[X2I], in , vars[H2I], i_h_tm1, vars[C2I], i_c_tm1});
    else
      if (dropout_rate > 0.f)
        i_ait = affine_transform({vars[BI], vars[X2I], cmult(in, masks_i[IA])});
      else
        i_ait = affine_transform({vars[BI], vars[X2I], in});
    Expression i_it = logistic(i_ait);
    // forget
    Expression i_ft = 1.f - i_it;
    // write memory cell
    Expression i_awt;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_awt = affine_transform({vars[BC], vars[X2C], cmult(in, masks_i[IW]), vars[H2C], cmult(i_h_tm1, masks_i[HW])});
      else
        i_awt = affine_transform({vars[BC], vars[X2C], in, vars[H2C], i_h_tm1});
    else
      if (dropout_rate > 0.f)
        i_awt = affine_transform({vars[BC], vars[X2C], cmult(in, masks_i[IW])});
      else
        i_awt = affine_transform({vars[BC], vars[X2C], in});
    Expression i_wt = tanh(i_awt);
    // output
    if (has_prev_state) {
      Expression i_nwt = cmult(i_it, i_wt);
      Expression i_crt = cmult(i_ft, i_c_tm1);
      ct[i] = i_crt + i_nwt;
    } else {
      ct[i] = cmult(i_it, i_wt);
    }

    Expression i_aot;
    if (has_prev_state)
      if (dropout_rate > 0.f)
        i_aot = affine_transform({vars[BO], vars[X2O], cmult(in, masks_i[IO]), vars[H2O], cmult(i_h_tm1, masks_i[HO]), vars[C2O], cmult(ct[i], masks_i[CO])});
      else
        i_aot = affine_transform({vars[BO], vars[X2O], in, vars[H2O], i_h_tm1, vars[C2O], ct[i]});
    else
      if (dropout_rate > 0.f)
        i_aot = affine_transform({vars[BO], vars[X2O], cmult(in, masks_i[IO]), vars[C2O], cmult(ct[i], masks_i[CO])});
      else
        i_aot = affine_transform({vars[BO], vars[X2O], in, vars[C2O], ct[i]});
    Expression i_ot = logistic(i_aot);
    Expression ph_t = tanh(ct[i]);
    in = ht[i] = cmult(i_ot, ph_t);
  }
  return ht.back();
}

void LSTMBuilder::copy(const RNNBuilder & rnn) {
  const LSTMBuilder & rnn_lstm = (const LSTMBuilder&)rnn;
  assert(params.size() == rnn_lstm.params.size());
  for (size_t i = 0; i < params.size(); ++i)
    for (size_t j = 0; j < params[i].size(); ++j)
      params[i][j] = rnn_lstm.params[i][j];
}

void LSTMBuilder::save_parameters_pretraining(const string& fname) const {
  cerr << "Writing LSTM parameters to " << fname << endl;
  ofstream of(fname);
  assert(of);
  boost::archive::binary_oarchive oa(of);
  std::string id = "LSTMBuilder:params";
  oa << id;
  oa << layers;
  for (unsigned i = 0; i < layers; ++i) {
    for (auto p : params[i]) {
      oa << p.get()->values;
    }
  }
}

void LSTMBuilder::load_parameters_pretraining(const string& fname) {
  cerr << "Loading LSTM parameters from " << fname << endl;
  ifstream of(fname);
  assert(of);
  boost::archive::binary_iarchive ia(of);
  std::string id;
  ia >> id;
  if (id != "LSTMBuilder:params") {
    cerr << "Bad id read\n";
    abort();
  }
  unsigned l = 0;
  ia >> l;
  if (l != layers) {
    cerr << "Bad number of layers\n";
    abort();
  }
  // TODO check other dimensions
  for (unsigned i = 0; i < layers; ++i) {
    for (auto p : params[i]) {
      ia >> p.get()->values;
    }
  }
}

template<class Archive>
void LSTMBuilder::serialize(Archive& ar, const unsigned int) {
  ar & boost::serialization::base_object<RNNBuilder>(*this);
  ar & params;
  ar & layers;
  ar & dropout_rate;
}
DYNET_SERIALIZE_IMPL(LSTMBuilder);

} // namespace dynet
<|endoftext|>