<commit_before>/*
Copyright (c) 2013, Tolga HOŞGÖR
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

#include "threadpool11/threadpool11.h"

namespace threadpool11
{
	Worker::Worker(Pool* const& pool) :
		pool(pool),
		init(0),
		work(nullptr),
		terminate(false),
		thread(std::bind(&Worker::execute, this))
	{
		//std::cout << std::this_thread::get_id() << " Worker created" << std::endl;
	}

	inline bool Worker::operator==(Worker const& other) const
	{
		return thread.get_id() == other.thread.get_id();
	}
	inline bool Worker::operator==(const Worker* other) const
	{
		return operator==(*other);
	}

	void Worker::execute()
	{
		//std::cout << std::this_thread::get_id() << " Execute called" << std::endl;
		{
			std::unique_lock<std::mutex> initLock(this->initMutex);
			std::unique_lock<std::mutex> lock(activatorMutex);
			init = 1;
			initialized.notify_one();
			initLock.unlock();
			activator.wait(lock);
		}

		while(!terminate)
		{
			std::unique_lock<std::mutex> lock(activatorMutex);
			//std::cout << "thread started" << std::endl;
			WORK:
			//std::cout << "work started 2" << std::endl;
			work();
			//std::cout << std::this_thread::get_id() <<  "-" << workPosted.native_handle()
			//	<< " Work called" << std::endl;
			pool->enqueuedWorkMutex.lock();
			if(pool->enqueuedWork.size() > 0)
			{
				work = std::move(pool->enqueuedWork.front());
				pool->enqueuedWork.pop_front();
				pool->enqueuedWorkMutex.unlock();
			//	std::cout << pool->enqueuedWork.size() << " got work from enqueue, going back to work" << std::endl;
				goto WORK;
			}
			pool->enqueuedWorkMutex.unlock();

			pool->notifyAllFinishedMutex.lock();
			pool->workerContainerMutex.lock();

			pool->activeWorkers.erase(poolIterator);
			pool->inactiveWorkers.emplace_front(this);

			if(pool->activeWorkers.size() == 0)
			{
			//	std::cout << "notify all finished" << std::endl;
				pool->notifyAllFinished.notify_one();
			}

			pool->workerContainerMutex.unlock();
			pool->notifyAllFinishedMutex.unlock();

			//std::cout << pool->activeWorkers.size() << " work finished" << std::endl;
			if(terminate)
				break;
			activator.wait(lock);
		}
		//std::cout << "terminating" << std::endl;
	}
}
<commit_msg>changed pool->notifyAllFinished.notify_one() to notify_all() so that waitAll is thread-safe.<commit_after>/*
Copyright (c) 2013, Tolga HOŞGÖR
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

#include "threadpool11/threadpool11.h"

namespace threadpool11
{
	Worker::Worker(Pool* const& pool) :
		pool(pool),
		init(0),
		work(nullptr),
		terminate(false),
		thread(std::bind(&Worker::execute, this))
	{
		//std::cout << std::this_thread::get_id() << " Worker created" << std::endl;
	}

	inline bool Worker::operator==(Worker const& other) const
	{
		return thread.get_id() == other.thread.get_id();
	}
	inline bool Worker::operator==(const Worker* other) const
	{
		return operator==(*other);
	}

	void Worker::execute()
	{
		//std::cout << std::this_thread::get_id() << " Execute called" << std::endl;
		{
			std::unique_lock<std::mutex> initLock(this->initMutex);
			std::unique_lock<std::mutex> lock(activatorMutex);
			init = 1;
			initialized.notify_one();
			initLock.unlock();
			activator.wait(lock);
		}

		while(!terminate)
		{
			std::unique_lock<std::mutex> lock(activatorMutex);
			//std::cout << "thread started" << std::endl;
			WORK:
			//std::cout << "work started 2" << std::endl;
			work();
			//std::cout << std::this_thread::get_id() <<  "-" << workPosted.native_handle()
			//	<< " Work called" << std::endl;
			pool->enqueuedWorkMutex.lock();
			if(pool->enqueuedWork.size() > 0)
			{
				work = std::move(pool->enqueuedWork.front());
				pool->enqueuedWork.pop_front();
				pool->enqueuedWorkMutex.unlock();
			//	std::cout << pool->enqueuedWork.size() << " got work from enqueue, going back to work" << std::endl;
				goto WORK;
			}
			pool->enqueuedWorkMutex.unlock();

			pool->notifyAllFinishedMutex.lock();
			pool->workerContainerMutex.lock();

			pool->activeWorkers.erase(poolIterator);
			pool->inactiveWorkers.emplace_front(this);

			if(pool->activeWorkers.size() == 0)
			{
			//	std::cout << "notify all finished" << std::endl;
				pool->notifyAllFinished.notify_all();
			}

			pool->workerContainerMutex.unlock();
			pool->notifyAllFinishedMutex.unlock();

			//std::cout << pool->activeWorkers.size() << " work finished" << std::endl;
			if(terminate)
				break;
			activator.wait(lock);
		}
		//std::cout << "terminating" << std::endl;
	}
}
<|endoftext|>


<commit_before>/*!
Copyright (c) 2013, 2014, Tolga HOŞGÖR
All rights reserved.

This file is part of threadpool11.

    threadpool11 is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    threadpool11 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 threadpool11.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "threadpool11/Pool.h"
#include "threadpool11/Worker.h"

namespace threadpool11
{

Worker::Worker(Pool* const& pool)
  : thread(std::bind(&Worker::execute, this, pool))
{
  //std::cout << std::this_thread::get_id() << " Worker created" << std::endl;
  thread.detach();
}

void Worker::execute(Pool* const& pool)
{
  const std::unique_ptr<Worker> self(this); //! auto de-allocation when thread is terminated

  while(true)
  {
    Work::Callable* work_;
    //std::cout << "\tThread " << std::this_thread::get_id() << " awaken." << std::endl;
    while(pool->work_queue.pop(work_))
    {
      const std::unique_ptr<Work::Callable> work(work_);
      --pool->work_queue_size;
      ++pool->active_worker_count;
      //std::cout << "\tThread " << std::this_thread::get_id() << " worked." << std::endl;
      if((*work)() == Work::Type::TERMINAL)
      {
        --pool->active_worker_count;
        --pool->worker_count;
        return;
      }

      --pool->active_worker_count;
    }

    if(pool->active_worker_count == 0)
	{
		std::unique_lock<std::mutex> notifyAllFinishedLock(pool->notify_all_finished_signal_mtx);
		pool->are_all_really_finished = true;
		pool->notify_all_finished_signal.notify_all();
	}

    //std::cout << "\tThread " << std::this_thread::get_id() << " will sleep." << std::endl;
    std::unique_lock<std::mutex> workSignalLock(pool->work_signal_mtx);
    pool->work_signal.wait(workSignalLock, [&pool](){ return (pool->work_queue_size.load()); });
  }
}

}
<commit_msg>formatting<commit_after>/*!
Copyright (c) 2013, 2014, Tolga HOŞGÖR
All rights reserved.

This file is part of threadpool11.

    threadpool11 is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    threadpool11 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 threadpool11.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "threadpool11/Pool.h"
#include "threadpool11/Worker.h"

namespace threadpool11
{

Worker::Worker(Pool* const& pool)
  : thread(std::bind(&Worker::execute, this, pool))
{
  //std::cout << std::this_thread::get_id() << " Worker created" << std::endl;
  thread.detach();
}

void Worker::execute(Pool* const& pool)
{
  const std::unique_ptr<Worker> self(this); //! auto de-allocation when thread is terminated

  while(true)
  {
    Work::Callable* work_;
    //std::cout << "\tThread " << std::this_thread::get_id() << " awaken." << std::endl;
    while(pool->work_queue.pop(work_))
    {
      const std::unique_ptr<Work::Callable> work(work_);
      --pool->work_queue_size;
      ++pool->active_worker_count;
      //std::cout << "\tThread " << std::this_thread::get_id() << " worked." << std::endl;
      if((*work)() == Work::Type::TERMINAL)
      {
        --pool->active_worker_count;
        --pool->worker_count;
        return;
      }

      --pool->active_worker_count;
    }

    if(pool->active_worker_count == 0)
    {
      std::unique_lock<std::mutex> notifyAllFinishedLock(pool->notify_all_finished_signal_mtx);
      pool->are_all_really_finished = true;
      pool->notify_all_finished_signal.notify_all();
    }

    //std::cout << "\tThread " << std::this_thread::get_id() << " will sleep." << std::endl;
    std::unique_lock<std::mutex> workSignalLock(pool->work_signal_mtx);
    pool->work_signal.wait(workSignalLock, [&pool](){ return (pool->work_queue_size.load()); });
  }
}

}
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SkeletonReader.cpp
 *
 *  Created on: Jan 04, 2018
 *      Author: Norbert Podhorszki pnorbert@ornl.gov
 */

#include "SkeletonReader.h"
#include "SkeletonReader.tcc"

#include <adios_error.h>

#include "adios2/helper/adiosFunctions.h" // CSVToVector

#include <iostream>

namespace adios2
{

SkeletonReader::SkeletonReader(IO &io, const std::string &name, const Mode mode,
                               MPI_Comm mpiComm)
: Engine("SkeletonReader", io, name, mode, mpiComm)
{
    m_EndMessage = " in call to IO Open SkeletonReader " + m_Name + "\n";
    MPI_Comm_rank(mpiComm, &m_ReaderRank);
    Init();
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " Open(" << m_Name
                  << ") in constructor." << std::endl;
    }
}

SkeletonReader::~SkeletonReader()
{
    /* m_Skeleton deconstructor does close and finalize */
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " deconstructor on "
                  << m_Name << "\n";
    }
}

StepStatus SkeletonReader::BeginStep(const StepMode mode,
                                     const float timeoutSeconds)
{
    // step info should be received from the writer side in BeginStep()
    // so this forced increase should not be here
    ++m_CurrentStep;

    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "   BeginStep() new step " << m_CurrentStep << "\n";
    }

    // If we reach the end of stream (writer is gone or explicitly tells the
    // reader)
    // we return EndOfStream to the reader application
    if (m_CurrentStep == 2)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "   forcefully returns End of Stream at this step\n";

        return StepStatus::EndOfStream;
    }

    // We should block until a new step arrives or reach the timeout

    // m_IO Variables and Attributes should be defined at this point
    // so that the application can inquire them and start getting data

    return StepStatus::OK;
}

void SkeletonReader::PerformGets()
{
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "     PerformGets()\n";
    }
    m_NeedPerformGets = false;
}

void SkeletonReader::EndStep()
{
    // EndStep should call PerformGets() if there are unserved GetDeferred()
    // requests
    if (m_NeedPerformGets)
    {
        PerformGets();
    }

    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << "   EndStep()\n";
    }
}

void SkeletonReader::Close(const int transportIndex)
{
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " Close(" << m_Name
                  << ")\n";
    }
}

// PRIVATE

#define declare_type(T)                                                        \
    void SkeletonReader::DoGetSync(Variable<T> &variable, T *data)             \
    {                                                                          \
        GetSyncCommon(variable, data);                                         \
    }                                                                          \
    void SkeletonReader::DoGetDeferred(Variable<T> &variable, T *data)         \
    {                                                                          \
        GetDeferredCommon(variable, data);                                     \
    }                                                                          \
    void SkeletonReader::DoGetDeferred(Variable<T> &variable, T &data)         \
    {                                                                          \
        GetDeferredCommon(variable, &data);                                    \
    }

ADIOS2_FOREACH_TYPE_1ARG(declare_type)
#undef declare_type

void SkeletonReader::Init()
{
    InitParameters();
    InitTransports();
}

void SkeletonReader::InitParameters()
{
    auto itVerbosity = m_IO.m_Parameters.find("verbose");
    if (itVerbosity != m_IO.m_Parameters.end())
    {
        m_Verbosity = std::stoi(itVerbosity->second);
        if (m_DebugMode)
        {
            if (m_Verbosity < 0 || m_Verbosity > 5)
                throw std::invalid_argument(
                    "ERROR: Method verbose argument must be an "
                    "integer in the range [0,5], in call to "
                    "Open or Engine constructor\n");
        }
    }
}

void SkeletonReader::InitTransports()
{
    // Nothing to process from m_IO.m_TransportsParameters
}

} // end namespace adios2
<commit_msg>remove include of adios 1.x header in skeleton engine<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * SkeletonReader.cpp
 *
 *  Created on: Jan 04, 2018
 *      Author: Norbert Podhorszki pnorbert@ornl.gov
 */

#include "SkeletonReader.h"
#include "SkeletonReader.tcc"

#include "adios2/helper/adiosFunctions.h" // CSVToVector

#include <iostream>

namespace adios2
{

SkeletonReader::SkeletonReader(IO &io, const std::string &name, const Mode mode,
                               MPI_Comm mpiComm)
: Engine("SkeletonReader", io, name, mode, mpiComm)
{
    m_EndMessage = " in call to IO Open SkeletonReader " + m_Name + "\n";
    MPI_Comm_rank(mpiComm, &m_ReaderRank);
    Init();
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " Open(" << m_Name
                  << ") in constructor." << std::endl;
    }
}

SkeletonReader::~SkeletonReader()
{
    /* m_Skeleton deconstructor does close and finalize */
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " deconstructor on "
                  << m_Name << "\n";
    }
}

StepStatus SkeletonReader::BeginStep(const StepMode mode,
                                     const float timeoutSeconds)
{
    // step info should be received from the writer side in BeginStep()
    // so this forced increase should not be here
    ++m_CurrentStep;

    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "   BeginStep() new step " << m_CurrentStep << "\n";
    }

    // If we reach the end of stream (writer is gone or explicitly tells the
    // reader)
    // we return EndOfStream to the reader application
    if (m_CurrentStep == 2)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "   forcefully returns End of Stream at this step\n";

        return StepStatus::EndOfStream;
    }

    // We should block until a new step arrives or reach the timeout

    // m_IO Variables and Attributes should be defined at this point
    // so that the application can inquire them and start getting data

    return StepStatus::OK;
}

void SkeletonReader::PerformGets()
{
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank
                  << "     PerformGets()\n";
    }
    m_NeedPerformGets = false;
}

void SkeletonReader::EndStep()
{
    // EndStep should call PerformGets() if there are unserved GetDeferred()
    // requests
    if (m_NeedPerformGets)
    {
        PerformGets();
    }

    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << "   EndStep()\n";
    }
}

void SkeletonReader::Close(const int transportIndex)
{
    if (m_Verbosity == 5)
    {
        std::cout << "Skeleton Reader " << m_ReaderRank << " Close(" << m_Name
                  << ")\n";
    }
}

// PRIVATE

#define declare_type(T)                                                        \
    void SkeletonReader::DoGetSync(Variable<T> &variable, T *data)             \
    {                                                                          \
        GetSyncCommon(variable, data);                                         \
    }                                                                          \
    void SkeletonReader::DoGetDeferred(Variable<T> &variable, T *data)         \
    {                                                                          \
        GetDeferredCommon(variable, data);                                     \
    }                                                                          \
    void SkeletonReader::DoGetDeferred(Variable<T> &variable, T &data)         \
    {                                                                          \
        GetDeferredCommon(variable, &data);                                    \
    }

ADIOS2_FOREACH_TYPE_1ARG(declare_type)
#undef declare_type

void SkeletonReader::Init()
{
    InitParameters();
    InitTransports();
}

void SkeletonReader::InitParameters()
{
    auto itVerbosity = m_IO.m_Parameters.find("verbose");
    if (itVerbosity != m_IO.m_Parameters.end())
    {
        m_Verbosity = std::stoi(itVerbosity->second);
        if (m_DebugMode)
        {
            if (m_Verbosity < 0 || m_Verbosity > 5)
                throw std::invalid_argument(
                    "ERROR: Method verbose argument must be an "
                    "integer in the range [0,5], in call to "
                    "Open or Engine constructor\n");
        }
    }
}

void SkeletonReader::InitTransports()
{
    // Nothing to process from m_IO.m_TransportsParameters
}

} // end namespace adios2
<|endoftext|>


<commit_before>#include "clustering/suggester/suggester.hpp"

#include "stl_utils.hpp"
#include "containers/priority_queue.hpp"

namespace {

struct priority_t {
    machine_id_t machine_id;

    bool pinned;
    bool would_rob_secondary;
    int redundancy_cost;
    float backfill_cost;

    priority_t() { }  // TODO: fix priority_queue_t

    priority_t(machine_id_t _machine_id, bool _pinned, bool _would_rob_secondary,
               int _redundancy_cost, float _backfill_cost)
        : machine_id(_machine_id), pinned(_pinned), would_rob_secondary(_would_rob_secondary),
          redundancy_cost(_redundancy_cost), backfill_cost(_backfill_cost)
    { }
};

//It's easier to think about this function if you imagine it as the answer to:
//is y of higher priority than x

bool operator<(const priority_t &x, const priority_t &y) {
//CONTINUE:
    //Round 1: Pinnings.
    //F I G H T
    if (x.pinned && !y.pinned) {
        return false;
    } else if (y.pinned && !x.pinned) {
        return true;
    }

    //Round 2: Would Rob Secondary.
    //F I G H T
    if (x.would_rob_secondary && !y.would_rob_secondary) {
        return true;
    } else if (y.would_rob_secondary && !x.would_rob_secondary) {
        return false;
    }

    //Round 3: Redundancy.
    //F I G H T
    if (x.redundancy_cost < y.redundancy_cost) {
        return false;
    } else if (y.redundancy_cost < x.redundancy_cost) {
        return true;
    }

    //Round 4: Backfill cost.
    //F I G H T
    if (x.backfill_cost < y.backfill_cost) {
        return false;
    } else if (y.backfill_cost < x.backfill_cost) {
        return true;
    }

    //You Lose!!
    //Continue?
    //(uncomment the below line to continue)
    //goto CONTINUE;
    //5
    //4
    //3
    //2
    //1
    //Last chance:
    //goto CONTINUE;
    //Didn't continue: Game Over
    return false; //They're equal
}

} //anonymous namespace

/* Returns a "score" indicating how expensive it would be to turn the machine
with the given business card into a primary or secondary for the given shard. */

template<class protocol_t>
float estimate_cost_to_get_up_to_date(
        const reactor_business_card_t<protocol_t> &business_card,
        const typename protocol_t::region_t &shard) {
    typedef reactor_business_card_t<protocol_t> rb_t;
    region_map_t<protocol_t, float> costs(shard, 3);
    for (typename rb_t::activity_map_t::const_iterator it = business_card.activities.begin();
            it != business_card.activities.end(); it++) {
        typename protocol_t::region_t intersection = region_intersection(it->second.region, shard);
        if (!region_is_empty(intersection)) {
            int cost;
            if (boost::get<typename rb_t::primary_when_safe_t>(&it->second.activity)) {
                cost = 0;
            } else if (boost::get<typename rb_t::primary_t>(&it->second.activity)) {
                cost = 0;
            } else if (boost::get<typename rb_t::secondary_up_to_date_t>(&it->second.activity)) {
                cost = 1;
            } else if (boost::get<typename rb_t::secondary_without_primary_t>(&it->second.activity)) {
                cost = 2;
            } else if (boost::get<typename rb_t::secondary_backfilling_t>(&it->second.activity)) {
                cost = 2;
            } else if (boost::get<typename rb_t::nothing_when_safe_t>(&it->second.activity)) {
                cost = 3;
            } else if (boost::get<typename rb_t::nothing_when_done_erasing_t>(&it->second.activity)) {
                cost = 3;
            } else if (boost::get<typename rb_t::nothing_t>(&it->second.activity)) {
                cost = 3;
            } else {
                // I don't know if this is unreachable, but cost would be uninitialized otherwise  - Sam
                // TODO: Is this really unreachable?
                unreachable();
            }
            /* It's ok to just call `set()` instead of trying to find the minimum
            because activities should never overlap. */
            costs.set(intersection, cost);
        }
    }
    float sum = 0;
    int count = 0;
    for (typename region_map_t<protocol_t, float>::iterator it = costs.begin(); it != costs.end(); it++) {
        /* TODO: Scale by how much data is in `it->first` */
        sum += it->second;
        count++;
    }
    return sum / count;
}

std::vector<machine_id_t> pick_n_best(priority_queue_t<priority_t> *candidates, int n, const datacenter_id_t &datacenter) {
    std::vector<machine_id_t> result;
    while (result.size() < static_cast<size_t>(n)) {
        if (candidates->empty()) {
            throw cannot_satisfy_goals_exc_t(strprintf("Didn't have enough unused machines in datacenter %s, we needed %d\n", uuid_to_str(datacenter).c_str(), n));
        } else {
            result.push_back(candidates->pop().machine_id);
        }
    }
    return result;
}

template<class protocol_t>
std::map<machine_id_t, blueprint_role_t> suggest_blueprint_for_shard(
        const std::map<machine_id_t, reactor_business_card_t<protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const typename protocol_t::region_t &shard,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const std::set<machine_id_t> &primary_pinnings,
        const std::set<machine_id_t> &secondary_pinnings,
        std::map<machine_id_t, int> *primary_usage,
        std::map<machine_id_t, int> *secondary_usage) {

    std::map<machine_id_t, blueprint_role_t> sub_blueprint;

    priority_queue_t<priority_t> primary_candidates;
    for (std::map<machine_id_t, datacenter_id_t>::const_iterator it = machine_data_centers.begin();
            it != machine_data_centers.end(); it++) {
        if (it->second == primary_datacenter) {
            bool pinned = std_contains(primary_pinnings, it->first);

            bool would_rob_secondary = std_contains(secondary_pinnings, it->first);

            int redundancy_cost = get_with_default(*primary_usage, it->first, 0);

            float backfill_cost;
            if (std_contains(directory, it->first)) {
                backfill_cost = estimate_cost_to_get_up_to_date(directory.find(it->first)->second, shard);
            } else {
                backfill_cost = 3.0;
            }

            primary_candidates.push(priority_t(it->first, pinned, would_rob_secondary, redundancy_cost, backfill_cost));
        }
    }
    machine_id_t primary = pick_n_best(&primary_candidates, 1, primary_datacenter).front();
    sub_blueprint[primary] = blueprint_role_primary;

    //Update primary_usage
    get_with_default(*primary_usage, primary, 0)++;

    for (std::map<datacenter_id_t, int>::const_iterator it = datacenter_affinities.begin(); it != datacenter_affinities.end(); it++) {
        priority_queue_t<priority_t> secondary_candidates;
        for (std::map<machine_id_t, datacenter_id_t>::const_iterator jt = machine_data_centers.begin();
                jt != machine_data_centers.end(); jt++) {
            if (jt->second == it->first && jt->first != primary) {
                bool pinned = std_contains(secondary_pinnings, jt->first);

                int redundancy_cost = get_with_default(*secondary_usage, jt->first, 0);

                bool would_rob_secondary = false; //we're the secondary, we shan't be robbing ourselves

                float backfill_cost;
                if (std_contains(directory, jt->first)) {
                    backfill_cost = estimate_cost_to_get_up_to_date(directory.find(jt->first)->second, shard);
                } else {
                    backfill_cost = 3.0;
                }

                secondary_candidates.push(priority_t(jt->first, pinned, would_rob_secondary, redundancy_cost, backfill_cost));
            }
        }
        std::vector<machine_id_t> secondaries = pick_n_best(&secondary_candidates, it->second, it->first);
        for (std::vector<machine_id_t>::iterator jt = secondaries.begin(); jt != secondaries.end(); jt++) {
            //Update secondary usage
            get_with_default(*secondary_usage, *jt, 0)++;
            sub_blueprint[*jt] = blueprint_role_secondary;
        }
    }

    for (std::map<machine_id_t, datacenter_id_t>::const_iterator it = machine_data_centers.begin();
            it != machine_data_centers.end(); it++) {
        /* This will set the value to `role_nothing` iff the peer is not already
        in the blueprint. */
        sub_blueprint.insert(std::make_pair(it->first, blueprint_role_nothing));
    }

    return sub_blueprint;
}

template<class protocol_t>
persistable_blueprint_t<protocol_t> suggest_blueprint(
        const std::map<machine_id_t, reactor_business_card_t<protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<typename protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<protocol_t, std::set<machine_id_t> > &secondary_pinnings) {

    typedef region_map_t<protocol_t, machine_id_t> primary_pinnings_map_t;
    typedef region_map_t<protocol_t, std::set<machine_id_t> > secondary_pinnings_map_t;

    persistable_blueprint_t<protocol_t> blueprint;

    //Maps to keep track of how much we're using each machine
    std::map<machine_id_t, int> primary_usage, secondary_usage;
    for (typename std::set<typename protocol_t::region_t>::const_iterator it = shards.begin();
            it != shards.end(); it++) {
        std::set<machine_id_t> machines_shard_primary_is_pinned_to;
        primary_pinnings_map_t primary_masked_map = primary_pinnings.mask(*it);

        for (typename primary_pinnings_map_t::iterator pit  = primary_masked_map.begin();
                                                       pit != primary_masked_map.end();
                                                       ++pit) {
            machines_shard_primary_is_pinned_to.insert(pit->second);
        }

        std::set<machine_id_t> machines_shard_secondary_is_pinned_to;
        secondary_pinnings_map_t secondary_masked_map = secondary_pinnings.mask(*it);

        for (typename secondary_pinnings_map_t::iterator pit  = secondary_masked_map.begin();
                                                         pit != secondary_masked_map.end();
                                                         ++pit) {
            machines_shard_secondary_is_pinned_to.insert(pit->second.begin(), pit->second.end());
        }

        std::map<machine_id_t, blueprint_role_t> shard_blueprint =
            suggest_blueprint_for_shard(directory, primary_datacenter, datacenter_affinities, *it,
                                        machine_data_centers, machines_shard_primary_is_pinned_to,
                                        machines_shard_secondary_is_pinned_to, &primary_usage,
                                        &secondary_usage);
        for (typename std::map<machine_id_t, blueprint_role_t>::iterator jt = shard_blueprint.begin();
                jt != shard_blueprint.end(); jt++) {
            blueprint.machines_roles[jt->first][*it] = jt->second;
        }
    }

    return blueprint;
}

#include "mock/dummy_protocol.hpp"

template
persistable_blueprint_t<mock::dummy_protocol_t> suggest_blueprint<mock::dummy_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<mock::dummy_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<mock::dummy_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<mock::dummy_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<mock::dummy_protocol_t, std::set<machine_id_t> > &secondary_pinnings);

#include "memcached/protocol.hpp"

template
persistable_blueprint_t<memcached_protocol_t> suggest_blueprint<memcached_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<memcached_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<memcached_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<memcached_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<memcached_protocol_t, std::set<machine_id_t> > &secondary_pinnings);

#include "rdb_protocol/protocol.hpp"

template
persistable_blueprint_t<rdb_protocol_t> suggest_blueprint<rdb_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<rdb_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<rdb_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<rdb_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<rdb_protocol_t, std::set<machine_id_t> > &secondary_pinnings);
<commit_msg>Allows for primary-datacenterless namespaces.<commit_after>#include "clustering/suggester/suggester.hpp"

#include "stl_utils.hpp"
#include "containers/priority_queue.hpp"

namespace {

struct priority_t {
    machine_id_t machine_id;

    bool pinned;
    bool would_rob_secondary;
    int redundancy_cost;
    float backfill_cost;

    priority_t() { }  // TODO: fix priority_queue_t

    priority_t(machine_id_t _machine_id, bool _pinned, bool _would_rob_secondary,
               int _redundancy_cost, float _backfill_cost)
        : machine_id(_machine_id), pinned(_pinned), would_rob_secondary(_would_rob_secondary),
          redundancy_cost(_redundancy_cost), backfill_cost(_backfill_cost)
    { }
};

//It's easier to think about this function if you imagine it as the answer to:
//is y of higher priority than x

bool operator<(const priority_t &x, const priority_t &y) {
//CONTINUE:
    //Round 1: Pinnings.
    //F I G H T
    if (x.pinned && !y.pinned) {
        return false;
    } else if (y.pinned && !x.pinned) {
        return true;
    }

    //Round 2: Would Rob Secondary.
    //F I G H T
    if (x.would_rob_secondary && !y.would_rob_secondary) {
        return true;
    } else if (y.would_rob_secondary && !x.would_rob_secondary) {
        return false;
    }

    //Round 3: Redundancy.
    //F I G H T
    if (x.redundancy_cost < y.redundancy_cost) {
        return false;
    } else if (y.redundancy_cost < x.redundancy_cost) {
        return true;
    }

    //Round 4: Backfill cost.
    //F I G H T
    if (x.backfill_cost < y.backfill_cost) {
        return false;
    } else if (y.backfill_cost < x.backfill_cost) {
        return true;
    }

    //You Lose!!
    //Continue?
    //(uncomment the below line to continue)
    //goto CONTINUE;
    //5
    //4
    //3
    //2
    //1
    //Last chance:
    //goto CONTINUE;
    //Didn't continue: Game Over
    return false; //They're equal
}

} //anonymous namespace

/* Returns a "score" indicating how expensive it would be to turn the machine
with the given business card into a primary or secondary for the given shard. */

template<class protocol_t>
float estimate_cost_to_get_up_to_date(
        const reactor_business_card_t<protocol_t> &business_card,
        const typename protocol_t::region_t &shard) {
    typedef reactor_business_card_t<protocol_t> rb_t;
    region_map_t<protocol_t, float> costs(shard, 3);
    for (typename rb_t::activity_map_t::const_iterator it = business_card.activities.begin();
            it != business_card.activities.end(); it++) {
        typename protocol_t::region_t intersection = region_intersection(it->second.region, shard);
        if (!region_is_empty(intersection)) {
            int cost;
            if (boost::get<typename rb_t::primary_when_safe_t>(&it->second.activity)) {
                cost = 0;
            } else if (boost::get<typename rb_t::primary_t>(&it->second.activity)) {
                cost = 0;
            } else if (boost::get<typename rb_t::secondary_up_to_date_t>(&it->second.activity)) {
                cost = 1;
            } else if (boost::get<typename rb_t::secondary_without_primary_t>(&it->second.activity)) {
                cost = 2;
            } else if (boost::get<typename rb_t::secondary_backfilling_t>(&it->second.activity)) {
                cost = 2;
            } else if (boost::get<typename rb_t::nothing_when_safe_t>(&it->second.activity)) {
                cost = 3;
            } else if (boost::get<typename rb_t::nothing_when_done_erasing_t>(&it->second.activity)) {
                cost = 3;
            } else if (boost::get<typename rb_t::nothing_t>(&it->second.activity)) {
                cost = 3;
            } else {
                // I don't know if this is unreachable, but cost would be uninitialized otherwise  - Sam
                // TODO: Is this really unreachable?
                unreachable();
            }
            /* It's ok to just call `set()` instead of trying to find the minimum
            because activities should never overlap. */
            costs.set(intersection, cost);
        }
    }
    float sum = 0;
    int count = 0;
    for (typename region_map_t<protocol_t, float>::iterator it = costs.begin(); it != costs.end(); it++) {
        /* TODO: Scale by how much data is in `it->first` */
        sum += it->second;
        count++;
    }
    return sum / count;
}

std::vector<machine_id_t> pick_n_best(priority_queue_t<priority_t> *candidates, int n, const datacenter_id_t &datacenter) {
    std::vector<machine_id_t> result;
    while (result.size() < static_cast<size_t>(n)) {
        if (candidates->empty()) {
            throw cannot_satisfy_goals_exc_t(strprintf("Didn't have enough unused machines in datacenter %s, we needed %d\n", uuid_to_str(datacenter).c_str(), n));
        } else {
            result.push_back(candidates->pop().machine_id);
        }
    }
    return result;
}

template<class protocol_t>
std::map<machine_id_t, blueprint_role_t> suggest_blueprint_for_shard(
        const std::map<machine_id_t, reactor_business_card_t<protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const typename protocol_t::region_t &shard,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const std::set<machine_id_t> &primary_pinnings,
        const std::set<machine_id_t> &secondary_pinnings,
        std::map<machine_id_t, int> *primary_usage,
        std::map<machine_id_t, int> *secondary_usage) {

    std::map<machine_id_t, blueprint_role_t> sub_blueprint;

    priority_queue_t<priority_t> primary_candidates;
    for (std::map<machine_id_t, datacenter_id_t>::const_iterator it = machine_data_centers.begin();
            it != machine_data_centers.end(); it++) {
        if (it->second == primary_datacenter || primary_datacenter.is_nil()) {
            bool pinned = std_contains(primary_pinnings, it->first);

            bool would_rob_secondary = std_contains(secondary_pinnings, it->first);

            int redundancy_cost = get_with_default(*primary_usage, it->first, 0);

            float backfill_cost;
            if (std_contains(directory, it->first)) {
                backfill_cost = estimate_cost_to_get_up_to_date(directory.find(it->first)->second, shard);
            } else {
                backfill_cost = 3.0;
            }

            primary_candidates.push(priority_t(it->first, pinned, would_rob_secondary, redundancy_cost, backfill_cost));
        }
    }
    machine_id_t primary = pick_n_best(&primary_candidates, 1, primary_datacenter).front();
    sub_blueprint[primary] = blueprint_role_primary;

    //Update primary_usage
    get_with_default(*primary_usage, primary, 0)++;

    for (std::map<datacenter_id_t, int>::const_iterator it = datacenter_affinities.begin(); it != datacenter_affinities.end(); it++) {
        priority_queue_t<priority_t> secondary_candidates;
        for (std::map<machine_id_t, datacenter_id_t>::const_iterator jt = machine_data_centers.begin();
                jt != machine_data_centers.end(); jt++) {
            if (jt->second == it->first && jt->first != primary) {
                bool pinned = std_contains(secondary_pinnings, jt->first);

                int redundancy_cost = get_with_default(*secondary_usage, jt->first, 0);

                bool would_rob_secondary = false; //we're the secondary, we shan't be robbing ourselves

                float backfill_cost;
                if (std_contains(directory, jt->first)) {
                    backfill_cost = estimate_cost_to_get_up_to_date(directory.find(jt->first)->second, shard);
                } else {
                    backfill_cost = 3.0;
                }

                secondary_candidates.push(priority_t(jt->first, pinned, would_rob_secondary, redundancy_cost, backfill_cost));
            }
        }
        std::vector<machine_id_t> secondaries = pick_n_best(&secondary_candidates, it->second, it->first);
        for (std::vector<machine_id_t>::iterator jt = secondaries.begin(); jt != secondaries.end(); jt++) {
            //Update secondary usage
            get_with_default(*secondary_usage, *jt, 0)++;
            sub_blueprint[*jt] = blueprint_role_secondary;
        }
    }

    for (std::map<machine_id_t, datacenter_id_t>::const_iterator it = machine_data_centers.begin();
            it != machine_data_centers.end(); it++) {
        /* This will set the value to `role_nothing` iff the peer is not already
        in the blueprint. */
        sub_blueprint.insert(std::make_pair(it->first, blueprint_role_nothing));
    }

    return sub_blueprint;
}

template<class protocol_t>
persistable_blueprint_t<protocol_t> suggest_blueprint(
        const std::map<machine_id_t, reactor_business_card_t<protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<typename protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<protocol_t, std::set<machine_id_t> > &secondary_pinnings) {

    typedef region_map_t<protocol_t, machine_id_t> primary_pinnings_map_t;
    typedef region_map_t<protocol_t, std::set<machine_id_t> > secondary_pinnings_map_t;

    persistable_blueprint_t<protocol_t> blueprint;

    //Maps to keep track of how much we're using each machine
    std::map<machine_id_t, int> primary_usage, secondary_usage;
    for (typename std::set<typename protocol_t::region_t>::const_iterator it = shards.begin();
            it != shards.end(); it++) {
        std::set<machine_id_t> machines_shard_primary_is_pinned_to;
        primary_pinnings_map_t primary_masked_map = primary_pinnings.mask(*it);

        for (typename primary_pinnings_map_t::iterator pit  = primary_masked_map.begin();
                                                       pit != primary_masked_map.end();
                                                       ++pit) {
            machines_shard_primary_is_pinned_to.insert(pit->second);
        }

        std::set<machine_id_t> machines_shard_secondary_is_pinned_to;
        secondary_pinnings_map_t secondary_masked_map = secondary_pinnings.mask(*it);

        for (typename secondary_pinnings_map_t::iterator pit  = secondary_masked_map.begin();
                                                         pit != secondary_masked_map.end();
                                                         ++pit) {
            machines_shard_secondary_is_pinned_to.insert(pit->second.begin(), pit->second.end());
        }

        std::map<machine_id_t, blueprint_role_t> shard_blueprint =
            suggest_blueprint_for_shard(directory, primary_datacenter, datacenter_affinities, *it,
                                        machine_data_centers, machines_shard_primary_is_pinned_to,
                                        machines_shard_secondary_is_pinned_to, &primary_usage,
                                        &secondary_usage);
        for (typename std::map<machine_id_t, blueprint_role_t>::iterator jt = shard_blueprint.begin();
                jt != shard_blueprint.end(); jt++) {
            blueprint.machines_roles[jt->first][*it] = jt->second;
        }
    }

    return blueprint;
}

#include "mock/dummy_protocol.hpp"

template
persistable_blueprint_t<mock::dummy_protocol_t> suggest_blueprint<mock::dummy_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<mock::dummy_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<mock::dummy_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<mock::dummy_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<mock::dummy_protocol_t, std::set<machine_id_t> > &secondary_pinnings);

#include "memcached/protocol.hpp"

template
persistable_blueprint_t<memcached_protocol_t> suggest_blueprint<memcached_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<memcached_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<memcached_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<memcached_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<memcached_protocol_t, std::set<machine_id_t> > &secondary_pinnings);

#include "rdb_protocol/protocol.hpp"

template
persistable_blueprint_t<rdb_protocol_t> suggest_blueprint<rdb_protocol_t>(
        const std::map<machine_id_t, reactor_business_card_t<rdb_protocol_t> > &directory,
        const datacenter_id_t &primary_datacenter,
        const std::map<datacenter_id_t, int> &datacenter_affinities,
        const std::set<rdb_protocol_t::region_t> &shards,
        const std::map<machine_id_t, datacenter_id_t> &machine_data_centers,
        const region_map_t<rdb_protocol_t, machine_id_t> &primary_pinnings,
        const region_map_t<rdb_protocol_t, std::set<machine_id_t> > &secondary_pinnings);
<|endoftext|>


<commit_before>// Copyright (c) 2013 The Chromium Embedded Framework 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 "cef_handler.h"

#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "message_delegate/app_message_delegate.h"
#include "message_delegate/app_window_message_delegate.h"
#include "helper.h"
#include "resource_util.h"
#include "platform_util.h"
#include "window_util.h"

namespace {

    CefRefPtr<ClientHandler> g_instance = NULL;
    const char kInterceptionPath[] = "/desktop_app/internals/";
    std::string kScriptLoader = "appWindow.loadScript('#URL#');";
    std::string kUnknownInternalContent = "Failed to load resource";

} // namespace

ClientHandler::ClientHandler()
    : is_closing_ (false),
      main_handle_ (NULL),
      status_icon_handle_ (NULL),
      account_manager_ (NULL)
{
  DCHECK(!g_instance);
  g_instance = this;
  callbackId = 0;
  CreateProcessMessageDelegates(process_message_delegates_);
}

ClientHandler::~ClientHandler() {
  g_instance = NULL;
}

// static
CefRefPtr<ClientHandler>
ClientHandler::GetInstance() {
  return g_instance;
}

void
ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  if (!GetBrowser()) {
    base::AutoLock lock_scope(lock_);
    // We need to keep the main child window, but not popup windows
    browser_ = browser;
    browser_id_ = browser->GetIdentifier();
    // ToDo: leaks
    main_handle_ = new BrowserWindow;
    main_handle_->WrapNative(browser->GetHost()->GetWindowHandle());
  } else if (browser->IsPopup()) {
    // Add to the list of popup browsers.
//    popup_browsers_.push_back(browser);

    // ToDo: leaks
    BrowserWindow *window = new BrowserWindow;
    window->WrapNative(browser->GetHost()->GetWindowHandle());

    // Give focus to the popup browser. Perform asynchronously because the
    // parent window may attempt to keep focus after launching the popup.
    CefPostTask(TID_UI,
       base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true));
  }
  // Add to the list of existing browsers.
  browser_list_.push_back(browser);
}

bool
ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  // Closing the main window requires special handling. See the DoClose()
  // documentation in the CEF header for a detailed destription of this
  // process.
  if (browser_list_.size() == 1) {
    // Set a flag to indicate that the window close should be allowed.
    is_closing_ = true;
  }

  // Allow the close. For windowed browsers this will result in the OS close
  // event being sent.
  if (!browser->IsPopup()) {
    // Dont' close main window, just hide it
    main_handle_->Hide();
    return true;
  }
  return false;
}

void
ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  // Remove from the list of existing browsers.
  BrowserList::iterator bit = browser_list_.begin();
  for (; bit != browser_list_.end(); ++bit) {
    if ((*bit)->IsSame(browser)) {
      browser_list_.erase(bit);
      break;
    }
  }

  if (browser_list_.empty()) {
    // All browser windows have closed. Quit the application message loop.
    CefQuitMessageLoop();
  } else if (!browser->IsPopup()) {
    // If we close main window - close all popups...
    CloseAllBrowsers(true);
  }
}

void
ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                ErrorCode errorCode,
                                const CefString& errorText,
                                const CefString& failedUrl) {
  CEF_REQUIRE_UI_THREAD();

  // Don't display an error for downloaded files.
  if (errorCode == ERR_ABORTED)
    return;

  std::stringstream error_explain;
  error_explain << std::string(failedUrl) <<
     ", with error" << std::string(errorText) <<
     " (" << errorCode << ")";

  LOG(INFO) << "Failed to load URL:" << error_explain.str();

  frame->LoadURL(GetAccountManager()->GetCurrentAccount()->GetBaseUrl() + "internals/pages/offline");
}

void
ClientHandler::OnLoadEnd(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   int httpStatusCode) {

  if (httpStatusCode != 200 || !frame->IsMain())
    return; // We need only successful loaded main frame

#if 0
  frame->ExecuteJavaScript(
     helper::string_replace(kScriptLoader, "#URL#", "http://ya.ru"),
     "",
     0
  );
#endif
  // Fix IM autoresize
  std::string code =
    "(function(window) {"
      "var event = document.createEvent('UIEvents');"
      "event.initUIEvent('resize', true, false, window, 0);"
      "window.dispatchEvent(event);"
    "})(window)";

  frame->ExecuteJavaScript(
     code,
     "",
     0
  );
}

void
ClientHandler::CloseAllBrowsers(bool force_close) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
        base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close));
    return;
  }

  if (browser_list_.empty())
    return;

  BrowserList::const_iterator it = browser_list_.begin();
  for (; it != browser_list_.end(); ++it)
    (*it)->GetHost()->CloseBrowser(force_close);
}

void
ClientHandler::CloseAllPopups(bool force_close) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
       base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close));
    return;
  }

  if (browser_list_.empty())
    return;

  BrowserList::const_iterator it = browser_list_.begin();
  for (; it != browser_list_.end(); ++it) {
    if (!(*it)->IsPopup())
      continue;

    (*it)->GetHost()->CloseBrowser(force_close);
  }

}

void
ClientHandler::OnBeforeContextMenu(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefContextMenuParams> params,
   CefRefPtr<CefMenuModel> model) {
  CEF_REQUIRE_UI_THREAD();

  if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
    // Add a separator if the menu already has items.
    if (model->GetCount() > 0)
      model->AddSeparator();

    // Add DevTools items to all context menus.
    model->AddItem(1, "&Show DevTools");
    model->AddItem(2, "Close DevTools");
    model->AddSeparator();
    model->AddItem(3, "Inspect Element");
  }
}

bool
ClientHandler::OnContextMenuCommand(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefContextMenuParams> params,
   int command_id,
   EventFlags event_flags) {
  CEF_REQUIRE_UI_THREAD();

  switch (command_id) {
    case 1:
      ShowDevTools(browser, CefPoint());
      return true;
    case 2:
      CloseDevTools(browser);
      return true;
    case 3:
      ShowDevTools(browser, CefPoint(params->GetXCoord(), params->GetYCoord()));
      return true;
    default:
      return false;
  }
}

void
ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
   const CefPoint& inspect_element_at) {
  CefWindowInfo windowInfo;
  CefBrowserSettings settings;

#if defined(OS_WIN)
  windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools");
#endif

  browser->GetHost()->ShowDevTools(windowInfo, this, settings,
     inspect_element_at);
}

void
ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
  browser->GetHost()->CloseDevTools();
}

bool
ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   const CefString& target_url,
   const CefString& target_frame_name,
   const CefPopupFeatures& popupFeatures,
   CefWindowInfo& windowInfo,
   CefRefPtr<CefClient>& client,
   CefBrowserSettings& settings,
   bool* no_javascript_access) {
  CEF_REQUIRE_IO_THREAD();

  std::string url = target_url;
  if (!IsAllowedUrl(url)) {
    platform_util::OpenExternal(url);
    return true;
  }

  return false;
}

bool
ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefRequest> request,
   bool is_redirect) {

  std::string url = request->GetURL();
  if (!IsAllowedUrl(url)) {
    platform_util::OpenExternal(url);
    return true;
  }

  return false;
}

CefRefPtr<CefResourceHandler>
ClientHandler::GetResourceHandler(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefRequest> request) {
  CEF_REQUIRE_IO_THREAD();

  std::string url = request->GetURL();
  if (url.find(kInterceptionPath) == std::string::npos)
    return NULL;

  // Handle URLs in interception path
  std::string file_name, mime_type;
  if (helper::ParseUrl(url, &file_name, &mime_type)) {
    // Remove interception path
    file_name = file_name.substr(strlen(kInterceptionPath) - 1);
    // Load the resource from file.
    CefRefPtr<CefStreamReader> stream =
       GetBinaryResourceReader(app_settings_.resource_dir, file_name.c_str());
    if (stream.get())
      return new CefStreamResourceHandler(mime_type, stream);
  }

  // Never let the internal links to the external world
  CefRefPtr<CefStreamReader> stream =
     CefStreamReader::CreateForData(
        static_cast<void*>(const_cast<char*>(kUnknownInternalContent.c_str())),
        kUnknownInternalContent.size()
     );
  ASSERT(stream.get());
  return new CefStreamResourceHandler("text/plain", stream);
}

bool
ClientHandler::OnProcessMessageReceived(
   CefRefPtr<CefBrowser> browser,
   CefProcessId source_process,
   CefRefPtr<CefProcessMessage> message) {
  bool handled = false;

  // Check for callbacks first
  if (message->GetName() == "executeCommandCallback") {
    int32 commandId = message->GetArgumentList()->GetInt(0);
    bool result = message->GetArgumentList()->GetBool(1);

    CefRefPtr<CommandCallback> callback = command_callback_map_[commandId];
    callback->CommandComplete(result);
    command_callback_map_.erase(commandId);

    handled = true;
  }

  std::string message_name = message->GetName();
  // Execute delegate callbacks.
  ProcessMessageDelegateSet::iterator it = process_message_delegates_.begin();
  for (; it != process_message_delegates_.end() && !handled; ++it) {
    if ((*it)->IsAcceptedNamespace(message_name)) {
      handled = (*it)->OnProcessMessageReceived(
         this,
         browser,
         source_process,
         message
      );
    }
  }

  if (!handled)
    LOG(WARNING) << "Unknown proccess message: " << message_name;

  return handled;
}

void
ClientHandler::SetAccountManager(CefRefPtr<AccountManager> account_manager) {
  account_manager_ = account_manager;
}

CefRefPtr<AccountManager>
ClientHandler::GetAccountManager() const {
  return account_manager_;
}

CefRefPtr<BrowserWindow>
ClientHandler::GetMainWindowHandle() const {
  CEF_REQUIRE_UI_THREAD();
  return main_handle_;
}

void
ClientHandler::SetAppSettings(AppSettings settings) {
 app_settings_ = settings;
}

AppSettings
ClientHandler::GetAppSettings() const {
  return app_settings_;
}

void
ClientHandler::SetStatusIconHandle(CefRefPtr<StatusIcon> handle) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
       base::Bind(&ClientHandler::SetStatusIconHandle, this, handle));
    return;
  }

  status_icon_handle_ = handle;
}

CefRefPtr<StatusIcon>
ClientHandler::GetStatusIconHandle() const {
  CEF_REQUIRE_UI_THREAD();
  return status_icon_handle_;
}

CefRefPtr<CefBrowser> ClientHandler::GetBrowser() const {
  base::AutoLock lock_scope(lock_);
  return browser_;
}

int
ClientHandler::GetBrowserId() const {
  base::AutoLock lock_scope(lock_);
  return browser_id_;
}

bool
ClientHandler::IsAllowedUrl(std::string url) {
  if (
    // Ugly temporary fix for file downloading...
    // ToDo: fix it!
    url.find("/desktop_app/download.file.php") != std::string::npos
    || url.find("/desktop_app/show.file.php") != std::string::npos
  )
    return false;

  return (
     account_manager_->GetCurrentAccount()->CheckBaseUrl(url)
     || url.find("chrome-devtools://") == 0
  );
}

void
ClientHandler::SwitchAccount(int id) {
  CloseAllPopups(true);
  // ToDo: delete host/domain cookies here!!!
  account_manager_->SwitchAccount(id);
  browser_->GetMainFrame()->LoadURL(
     account_manager_->GetCurrentAccount()->GetBaseUrl() + "internals/pages/portal-loader#login=yes"
  );
  account_manager_->Commit();
}

bool
ClientHandler::SendJSEvent(CefRefPtr<CefBrowser> browser, const CefString& name, const CefString& data)
{
  CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("dispatchEvent");
  message->GetArgumentList()->SetString(0, name);
  if (!data.empty())
    message->GetArgumentList()->SetString(1, data);

  browser->SendProcessMessage(PID_RENDERER, message);

  return true;
}

// static
void
ClientHandler::CreateProcessMessageDelegates(ProcessMessageDelegateSet& delegates) {
  AppMessageDelegate::CreateProcessMessageDelegates(delegates);
  AppWindowMessageDelegate::CreateProcessMessageDelegates(delegates);
}<commit_msg>Оставляем закрытие окна в покое. Закрытие это закрытие, сворачивание это сворачивание.<commit_after>// Copyright (c) 2013 The Chromium Embedded Framework 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 "cef_handler.h"

#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "message_delegate/app_message_delegate.h"
#include "message_delegate/app_window_message_delegate.h"
#include "helper.h"
#include "resource_util.h"
#include "platform_util.h"
#include "window_util.h"

namespace {

    CefRefPtr<ClientHandler> g_instance = NULL;
    const char kInterceptionPath[] = "/desktop_app/internals/";
    std::string kScriptLoader = "appWindow.loadScript('#URL#');";
    std::string kUnknownInternalContent = "Failed to load resource";

} // namespace

ClientHandler::ClientHandler()
    : is_closing_ (false),
      main_handle_ (NULL),
      status_icon_handle_ (NULL),
      account_manager_ (NULL)
{
  DCHECK(!g_instance);
  g_instance = this;
  callbackId = 0;
  CreateProcessMessageDelegates(process_message_delegates_);
}

ClientHandler::~ClientHandler() {
  g_instance = NULL;
}

// static
CefRefPtr<ClientHandler>
ClientHandler::GetInstance() {
  return g_instance;
}

void
ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  if (!GetBrowser()) {
    base::AutoLock lock_scope(lock_);
    // We need to keep the main child window, but not popup windows
    browser_ = browser;
    browser_id_ = browser->GetIdentifier();
    // ToDo: leaks
    main_handle_ = new BrowserWindow;
    main_handle_->WrapNative(browser->GetHost()->GetWindowHandle());
  } else if (browser->IsPopup()) {
    // Add to the list of popup browsers.
//    popup_browsers_.push_back(browser);

    // ToDo: leaks
    BrowserWindow *window = new BrowserWindow;
    window->WrapNative(browser->GetHost()->GetWindowHandle());

    // Give focus to the popup browser. Perform asynchronously because the
    // parent window may attempt to keep focus after launching the popup.
    CefPostTask(TID_UI,
       base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true));
  }
  // Add to the list of existing browsers.
  browser_list_.push_back(browser);
}

bool
ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  // Closing the main window requires special handling. See the DoClose()
  // documentation in the CEF header for a detailed destription of this
  // process.
  if (browser_list_.size() == 1) {
    // Set a flag to indicate that the window close should be allowed.
    is_closing_ = true;
  }

  return false;
}

void
ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();

  // Remove from the list of existing browsers.
  BrowserList::iterator bit = browser_list_.begin();
  for (; bit != browser_list_.end(); ++bit) {
    if ((*bit)->IsSame(browser)) {
      browser_list_.erase(bit);
      break;
    }
  }

  if (browser_list_.empty()) {
    // All browser windows have closed. Quit the application message loop.
    CefQuitMessageLoop();
  } else if (!browser->IsPopup()) {
    // If we close main window - close all popups...
    CloseAllBrowsers(true);
  }
}

void
ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                ErrorCode errorCode,
                                const CefString& errorText,
                                const CefString& failedUrl) {
  CEF_REQUIRE_UI_THREAD();

  // Don't display an error for downloaded files.
  if (errorCode == ERR_ABORTED)
    return;

  std::stringstream error_explain;
  error_explain << std::string(failedUrl) <<
     ", with error" << std::string(errorText) <<
     " (" << errorCode << ")";

  LOG(INFO) << "Failed to load URL:" << error_explain.str();

  frame->LoadURL(GetAccountManager()->GetCurrentAccount()->GetBaseUrl() + "internals/pages/offline");
}

void
ClientHandler::OnLoadEnd(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   int httpStatusCode) {

  if (httpStatusCode != 200 || !frame->IsMain())
    return; // We need only successful loaded main frame

#if 0
  frame->ExecuteJavaScript(
     helper::string_replace(kScriptLoader, "#URL#", "http://ya.ru"),
     "",
     0
  );
#endif
  // Fix IM autoresize
  std::string code =
    "(function(window) {"
      "var event = document.createEvent('UIEvents');"
      "event.initUIEvent('resize', true, false, window, 0);"
      "window.dispatchEvent(event);"
    "})(window)";

  frame->ExecuteJavaScript(
     code,
     "",
     0
  );
}

void
ClientHandler::CloseAllBrowsers(bool force_close) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
        base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close));
    return;
  }

  if (browser_list_.empty())
    return;

  BrowserList::const_iterator it = browser_list_.begin();
  for (; it != browser_list_.end(); ++it)
    (*it)->GetHost()->CloseBrowser(force_close);
}

void
ClientHandler::CloseAllPopups(bool force_close) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
       base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close));
    return;
  }

  if (browser_list_.empty())
    return;

  BrowserList::const_iterator it = browser_list_.begin();
  for (; it != browser_list_.end(); ++it) {
    if (!(*it)->IsPopup())
      continue;

    (*it)->GetHost()->CloseBrowser(force_close);
  }

}

void
ClientHandler::OnBeforeContextMenu(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefContextMenuParams> params,
   CefRefPtr<CefMenuModel> model) {
  CEF_REQUIRE_UI_THREAD();

  if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
    // Add a separator if the menu already has items.
    if (model->GetCount() > 0)
      model->AddSeparator();

    // Add DevTools items to all context menus.
    model->AddItem(1, "&Show DevTools");
    model->AddItem(2, "Close DevTools");
    model->AddSeparator();
    model->AddItem(3, "Inspect Element");
  }
}

bool
ClientHandler::OnContextMenuCommand(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefContextMenuParams> params,
   int command_id,
   EventFlags event_flags) {
  CEF_REQUIRE_UI_THREAD();

  switch (command_id) {
    case 1:
      ShowDevTools(browser, CefPoint());
      return true;
    case 2:
      CloseDevTools(browser);
      return true;
    case 3:
      ShowDevTools(browser, CefPoint(params->GetXCoord(), params->GetYCoord()));
      return true;
    default:
      return false;
  }
}

void
ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
   const CefPoint& inspect_element_at) {
  CefWindowInfo windowInfo;
  CefBrowserSettings settings;

#if defined(OS_WIN)
  windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools");
#endif

  browser->GetHost()->ShowDevTools(windowInfo, this, settings,
     inspect_element_at);
}

void
ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
  browser->GetHost()->CloseDevTools();
}

bool
ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   const CefString& target_url,
   const CefString& target_frame_name,
   const CefPopupFeatures& popupFeatures,
   CefWindowInfo& windowInfo,
   CefRefPtr<CefClient>& client,
   CefBrowserSettings& settings,
   bool* no_javascript_access) {
  CEF_REQUIRE_IO_THREAD();

  std::string url = target_url;
  if (!IsAllowedUrl(url)) {
    platform_util::OpenExternal(url);
    return true;
  }

  return false;
}

bool
ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefRequest> request,
   bool is_redirect) {

  std::string url = request->GetURL();
  if (!IsAllowedUrl(url)) {
    platform_util::OpenExternal(url);
    return true;
  }

  return false;
}

CefRefPtr<CefResourceHandler>
ClientHandler::GetResourceHandler(
   CefRefPtr<CefBrowser> browser,
   CefRefPtr<CefFrame> frame,
   CefRefPtr<CefRequest> request) {
  CEF_REQUIRE_IO_THREAD();

  std::string url = request->GetURL();
  if (url.find(kInterceptionPath) == std::string::npos)
    return NULL;

  // Handle URLs in interception path
  std::string file_name, mime_type;
  if (helper::ParseUrl(url, &file_name, &mime_type)) {
    // Remove interception path
    file_name = file_name.substr(strlen(kInterceptionPath) - 1);
    // Load the resource from file.
    CefRefPtr<CefStreamReader> stream =
       GetBinaryResourceReader(app_settings_.resource_dir, file_name.c_str());
    if (stream.get())
      return new CefStreamResourceHandler(mime_type, stream);
  }

  // Never let the internal links to the external world
  CefRefPtr<CefStreamReader> stream =
     CefStreamReader::CreateForData(
        static_cast<void*>(const_cast<char*>(kUnknownInternalContent.c_str())),
        kUnknownInternalContent.size()
     );
  ASSERT(stream.get());
  return new CefStreamResourceHandler("text/plain", stream);
}

bool
ClientHandler::OnProcessMessageReceived(
   CefRefPtr<CefBrowser> browser,
   CefProcessId source_process,
   CefRefPtr<CefProcessMessage> message) {
  bool handled = false;

  // Check for callbacks first
  if (message->GetName() == "executeCommandCallback") {
    int32 commandId = message->GetArgumentList()->GetInt(0);
    bool result = message->GetArgumentList()->GetBool(1);

    CefRefPtr<CommandCallback> callback = command_callback_map_[commandId];
    callback->CommandComplete(result);
    command_callback_map_.erase(commandId);

    handled = true;
  }

  std::string message_name = message->GetName();
  // Execute delegate callbacks.
  ProcessMessageDelegateSet::iterator it = process_message_delegates_.begin();
  for (; it != process_message_delegates_.end() && !handled; ++it) {
    if ((*it)->IsAcceptedNamespace(message_name)) {
      handled = (*it)->OnProcessMessageReceived(
         this,
         browser,
         source_process,
         message
      );
    }
  }

  if (!handled)
    LOG(WARNING) << "Unknown proccess message: " << message_name;

  return handled;
}

void
ClientHandler::SetAccountManager(CefRefPtr<AccountManager> account_manager) {
  account_manager_ = account_manager;
}

CefRefPtr<AccountManager>
ClientHandler::GetAccountManager() const {
  return account_manager_;
}

CefRefPtr<BrowserWindow>
ClientHandler::GetMainWindowHandle() const {
  CEF_REQUIRE_UI_THREAD();
  return main_handle_;
}

void
ClientHandler::SetAppSettings(AppSettings settings) {
 app_settings_ = settings;
}

AppSettings
ClientHandler::GetAppSettings() const {
  return app_settings_;
}

void
ClientHandler::SetStatusIconHandle(CefRefPtr<StatusIcon> handle) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
       base::Bind(&ClientHandler::SetStatusIconHandle, this, handle));
    return;
  }

  status_icon_handle_ = handle;
}

CefRefPtr<StatusIcon>
ClientHandler::GetStatusIconHandle() const {
  CEF_REQUIRE_UI_THREAD();
  return status_icon_handle_;
}

CefRefPtr<CefBrowser> ClientHandler::GetBrowser() const {
  base::AutoLock lock_scope(lock_);
  return browser_;
}

int
ClientHandler::GetBrowserId() const {
  base::AutoLock lock_scope(lock_);
  return browser_id_;
}

bool
ClientHandler::IsAllowedUrl(std::string url) {
  if (
    // Ugly temporary fix for file downloading...
    // ToDo: fix it!
    url.find("/desktop_app/download.file.php") != std::string::npos
    || url.find("/desktop_app/show.file.php") != std::string::npos
  )
    return false;

  return (
     account_manager_->GetCurrentAccount()->CheckBaseUrl(url)
     || url.find("chrome-devtools://") == 0
  );
}

void
ClientHandler::SwitchAccount(int id) {
  CloseAllPopups(true);
  // ToDo: delete host/domain cookies here!!!
  account_manager_->SwitchAccount(id);
  browser_->GetMainFrame()->LoadURL(
     account_manager_->GetCurrentAccount()->GetBaseUrl() + "internals/pages/portal-loader#login=yes"
  );
  account_manager_->Commit();
}

bool
ClientHandler::SendJSEvent(CefRefPtr<CefBrowser> browser, const CefString& name, const CefString& data)
{
  CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("dispatchEvent");
  message->GetArgumentList()->SetString(0, name);
  if (!data.empty())
    message->GetArgumentList()->SetString(1, data);

  browser->SendProcessMessage(PID_RENDERER, message);

  return true;
}

// static
void
ClientHandler::CreateProcessMessageDelegates(ProcessMessageDelegateSet& delegates) {
  AppMessageDelegate::CreateProcessMessageDelegates(delegates);
  AppWindowMessageDelegate::CreateProcessMessageDelegates(delegates);
}<|endoftext|>


<commit_before>//===============================================================================
// @ IvMainOGL.cpp
//
// Start up and main event loop for OpenGL
// ------------------------------------------------------------------------------
// Copyright (C) 2008-2015 by James M. Van Verth and Lars M. Bishop.
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//===============================================================================

//-------------------------------------------------------------------------------
//-- Dependencies ---------------------------------------------------------------
//-------------------------------------------------------------------------------

#include <stdlib.h>

#if !defined(__APPLE__) || !defined(__MACH__)
#include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>

#include <IvGame.h>
#include <IvDebugger.h>
#include <IvEventHandler.h>
#include <OGL/IvRendererOGL.h>

static void visibilityCallback(GLFWwindow* window, int vis);
static void reshapeCallback(GLFWwindow* window, int w, int h);

static void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void mouseCallback(GLFWwindow* window, int button, int action, int mods);

static void error_callback(int error, const char* description)
{
    ERROR_OUT(description << std::endl);
}

static GLFWwindow* window = nullptr;

//-------------------------------------------------------------------------------
// @ main()
//-------------------------------------------------------------------------------
// Where it all begins
//-------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    gDebugger.DumpToFile( "Debug.txt" );
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    {
        ERROR_OUT("Error: could not initialize GLFW" << std::endl);
    }

    // set up for core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);

    // set up display
    bool fullscreen = false;
    if (fullscreen)
    {
        window = glfwCreateWindow(640, 480, "Example", glfwGetPrimaryMonitor(), nullptr);
    }
    else
    {
        window = glfwCreateWindow(640, 480, "Example", nullptr, nullptr);
    }
    if (nullptr == window)
    {
        ERROR_OUT("Error: could not create window" << std::endl);
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent(window);

#if !defined(__APPLE__) || !defined(__MACH__)
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if ( GLEW_OK != err )
    {
        ERROR_OUT("Error: " << glewGetErrorString(err) << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // check for version compatibility
    if ( !GLEW_VERSION_3_2 )
    {
        ERROR_OUT("Error: OpenGL version 3.2 is not supported." << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    DEBUG_OUT("Using GLEW " << glewGetString(GLEW_VERSION));
#endif

    // set up game
    if (!IvGame::Create() || !IvGame::mGame->PreRendererInitialize( argc, argv ))
    {
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up renderer

    int width;
    int height;
    glfwGetFramebufferSize(window, &width, &height);

    if (!IvRendererOGL::Create() || !IvRendererOGL::mRenderer->Initialize( width, height ))
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // Set the background dark blue
    IvRenderer::mRenderer->SetClearColor( 0.0f, 0.0f, 0.10f, 1.0f );

    // Do post-renderer creation initialization
    if (!IvGame::mGame->PostRendererInitialize())
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up display callbacks
    glfwSetWindowFocusCallback(window, visibilityCallback);
    glfwSetWindowSizeCallback(window, reshapeCallback);

    // set up event handlers
    glfwSetKeyCallback(window, keyboardCallback);
    glfwSetMouseButtonCallback(window, mouseCallback);

    // run it!
    while (!glfwWindowShouldClose(window))
    {
        // game does everything it needs to do
        IvGame::mGame->Update();

        // clear the back buffer
        IvRenderer::mRenderer->ClearBuffers(kColorDepthClear);

        // render the world
        if ( IvRenderer::mRenderer->IsActive() )
        {
            IvGame::mGame->Display();
        }

        // swap graphics buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    IvGame::Destroy();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;

}   // End of main()

static void
visibilityCallback(GLFWwindow* window, int vis)
{
    IvRenderer::mRenderer->Activate( vis == GL_TRUE );
}

static void
reshapeCallback(GLFWwindow* window, int w, int h)
{
    IvRenderer::mRenderer->Resize( w, h );
}

static void
keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS || action == GLFW_REPEAT)
    {
        IvGame::mGame->mEventHandler->KeyDown( key );   // Handle key down event
    }
    else
    {
        IvGame::mGame->mEventHandler->KeyUp( key ); // Handle key up event
    }

}

static void
mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
    if ( button == GLFW_MOUSE_BUTTON_LEFT )
    {
        if ( action == GLFW_PRESS )
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);
            IvGame::mGame->mEventHandler->MouseDown( (int)x, (int)y );
        }
        else
        {
            IvGame::mGame->mEventHandler->MouseUp();
        }
    }
}

//-------------------------------------------------------------------------------
// @ GetTime()
//-------------------------------------------------------------------------------
// Get current system time in milliseconds
//-------------------------------------------------------------------------------
unsigned int
GetTime()
{
    return static_cast<unsigned int>(glfwGetTime()*1000.0f);
}

//-------------------------------------------------------------------------------
// @ SetWindowTitle()
//-------------------------------------------------------------------------------
// Set the current window title to the string value
//-------------------------------------------------------------------------------
void
SetWindowTitle( const char* title )
{
    glfwSetWindowTitle( window, title );
}

<commit_msg>Fix command key triggering 'w' on Mac<commit_after>//===============================================================================
// @ IvMainOGL.cpp
//
// Start up and main event loop for OpenGL
// ------------------------------------------------------------------------------
// Copyright (C) 2008-2015 by James M. Van Verth and Lars M. Bishop.
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//===============================================================================

//-------------------------------------------------------------------------------
//-- Dependencies ---------------------------------------------------------------
//-------------------------------------------------------------------------------

#include <stdlib.h>

#if !defined(__APPLE__) || !defined(__MACH__)
#include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>

#include <IvGame.h>
#include <IvDebugger.h>
#include <IvEventHandler.h>
#include <OGL/IvRendererOGL.h>

static void visibilityCallback(GLFWwindow* window, int vis);
static void reshapeCallback(GLFWwindow* window, int w, int h);

static void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void mouseCallback(GLFWwindow* window, int button, int action, int mods);

static void error_callback(int error, const char* description)
{
    ERROR_OUT(description << std::endl);
}

static GLFWwindow* window = nullptr;

//-------------------------------------------------------------------------------
// @ main()
//-------------------------------------------------------------------------------
// Where it all begins
//-------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    gDebugger.DumpToFile( "Debug.txt" );
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    {
        ERROR_OUT("Error: could not initialize GLFW" << std::endl);
    }

    // set up for core profile
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);

    // set up display
    bool fullscreen = false;
    if (fullscreen)
    {
        window = glfwCreateWindow(640, 480, "Example", glfwGetPrimaryMonitor(), nullptr);
    }
    else
    {
        window = glfwCreateWindow(640, 480, "Example", nullptr, nullptr);
    }
    if (nullptr == window)
    {
        ERROR_OUT("Error: could not create window" << std::endl);
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent(window);

#if !defined(__APPLE__) || !defined(__MACH__)
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if ( GLEW_OK != err )
    {
        ERROR_OUT("Error: " << glewGetErrorString(err) << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // check for version compatibility
    if ( !GLEW_VERSION_3_2 )
    {
        ERROR_OUT("Error: OpenGL version 3.2 is not supported." << std::endl);
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    DEBUG_OUT("Using GLEW " << glewGetString(GLEW_VERSION));
#endif

    // set up game
    if (!IvGame::Create() || !IvGame::mGame->PreRendererInitialize( argc, argv ))
    {
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up renderer

    int width;
    int height;
    glfwGetFramebufferSize(window, &width, &height);

    if (!IvRendererOGL::Create() || !IvRendererOGL::mRenderer->Initialize( width, height ))
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // Set the background dark blue
    IvRenderer::mRenderer->SetClearColor( 0.0f, 0.0f, 0.10f, 1.0f );

    // Do post-renderer creation initialization
    if (!IvGame::mGame->PostRendererInitialize())
    {
        IvRenderer::Destroy();
        IvGame::Destroy();
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // set up display callbacks
    glfwSetWindowFocusCallback(window, visibilityCallback);
    glfwSetWindowSizeCallback(window, reshapeCallback);

    // set up event handlers
    glfwSetKeyCallback(window, keyboardCallback);
    glfwSetMouseButtonCallback(window, mouseCallback);

    // run it!
    while (!glfwWindowShouldClose(window))
    {
        // game does everything it needs to do
        IvGame::mGame->Update();

        // clear the back buffer
        IvRenderer::mRenderer->ClearBuffers(kColorDepthClear);

        // render the world
        if ( IvRenderer::mRenderer->IsActive() )
        {
            IvGame::mGame->Display();
        }

        // swap graphics buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    IvGame::Destroy();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;

}   // End of main()

static void
visibilityCallback(GLFWwindow* window, int vis)
{
    IvRenderer::mRenderer->Activate( vis == GL_TRUE );
}

static void
reshapeCallback(GLFWwindow* window, int w, int h)
{
    IvRenderer::mRenderer->Resize( w, h );
}

static void
keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // only handle ASCII chars
    if (key > 127)
    {
        return;
    }

    if (action == GLFW_PRESS || action == GLFW_REPEAT)
    {
        IvGame::mGame->mEventHandler->KeyDown( key );   // Handle key down event
    }
    else
    {
        IvGame::mGame->mEventHandler->KeyUp( key ); // Handle key up event
    }

}

static void
mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
    if ( button == GLFW_MOUSE_BUTTON_LEFT )
    {
        if ( action == GLFW_PRESS )
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);
            IvGame::mGame->mEventHandler->MouseDown( (int)x, (int)y );
        }
        else
        {
            IvGame::mGame->mEventHandler->MouseUp();
        }
    }
}

//-------------------------------------------------------------------------------
// @ GetTime()
//-------------------------------------------------------------------------------
// Get current system time in milliseconds
//-------------------------------------------------------------------------------
unsigned int
GetTime()
{
    return static_cast<unsigned int>(glfwGetTime()*1000.0f);
}

//-------------------------------------------------------------------------------
// @ SetWindowTitle()
//-------------------------------------------------------------------------------
// Set the current window title to the string value
//-------------------------------------------------------------------------------
void
SetWindowTitle( const char* title )
{
    glfwSetWindowTitle( window, title );
}

<|endoftext|>