<commit_before>/*
 * Copyright 2009, 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <esnpapi.h>
#include <org/w3c/dom.h>

#include <assert.h>

std::map<const std::string, Object* (*)(ProxyObject object)> ProxyControl::proxyConstructorMap;

ProxyControl::ProxyControl(NPP npp) :
    npp(npp),
    nestingCount(1)
{
}

ProxyControl::~ProxyControl()
{
    // TODO: Release objects in newList and oldList
}

Object* ProxyControl::createProxy(NPObject* object, const Reflect::Type type)
{
    if (!object)
    {
        return 0;
    }

    std::string className = getInterfaceName(npp, object);
    if (className == "Object")
    {
        // TODO: We should define 'Object' interface
        return 0;
    }

    bool usedHint = false;
    for (;;)
    {
        std::map<const std::string, Object* (*)(ProxyObject object)>::iterator it;
        it = proxyConstructorMap.find(className);
        if (it != proxyConstructorMap.end())
        {
            ProxyObject browserObject(object, npp);
            if (Object* object = (*it).second(browserObject))
            {
                return track(object);
            }
        }
        if (!type.isObject() || usedHint)
        {
            break;
        }
        className = type.getQualifiedName();
        size_t pos = className.rfind(':');
        if (pos != std::string::npos)
        {
            className = className.substr(pos + 1);
            printf("%s: use the class name '%s' as hinted.\n", __func__, className.c_str());
        }
        usedHint = true;
    }
    return 0;
}

long ProxyControl::enter()
{
    return ++nestingCount;
}

long ProxyControl::leave()
{
    --nestingCount;
    assert(0 <= nestingCount);
    if (nestingCount == 0)
    {
        while (!newList.empty())
        {
            Object* object = newList.front();
            newList.pop_front();
            if (0 < object->release())
            {
                oldList.push_back(object);
            }
        }
    }
    return nestingCount;
}

void ProxyControl::registerMetaData(const char* meta, Object* (*createProxy)(ProxyObject object), const char* alias)
{
    Reflect::Interface interface(meta);
    std::string name = interface.getName();
    if (alias)
    {
        name = alias;
    }
    proxyConstructorMap[name] = createProxy;
    printf("%s\n", name.c_str());
}

ProxyObject::ProxyObject(NPObject* object, NPP npp) :
    object(object),
    npp(npp),
    count(0)
{
}

ProxyObject::ProxyObject(const ProxyObject& original) :
    object(original.object),
    npp(original.npp),
    count(original.count)
{
}

ProxyObject::~ProxyObject()
{
}

unsigned int ProxyObject::retain()
{
    NPN_RetainObject(object);
    return ++count;
}

unsigned int ProxyObject::release()
{
    if (0 < count)
    {
        NPN_ReleaseObject(object);
        --count;
    }
    if (count == 0)
    {
        delete this;
        return 0;
    }
    return count;
}

unsigned int ProxyObject::mark()
{
    return ++count;
}

PluginInstance::PluginInstance(NPP npp, NPObject* window) :
    proxyControl(npp),
    stubControl(npp),
    window(0)
{
    npp->pdata = this;
    this->window = interface_cast<org::w3c::dom::html::Window*>(proxyControl.createProxy(window, Reflect::Type("O14::html::Window")));
    if (this->window)
    {
        ProxyObject* proxy = interface_cast<ProxyObject*>(this->window);
        proxy->mark();
        proxy->retain();
    }
}

PluginInstance::~PluginInstance()
{
    if (window)
    {
        window->release();
    }
}

<commit_msg>(~ProxyObject) : Add a TODO item.<commit_after>/*
 * Copyright 2009, 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <esnpapi.h>
#include <org/w3c/dom.h>

#include <assert.h>

std::map<const std::string, Object* (*)(ProxyObject object)> ProxyControl::proxyConstructorMap;

ProxyControl::ProxyControl(NPP npp) :
    npp(npp),
    nestingCount(1)
{
}

ProxyControl::~ProxyControl()
{
    // TODO: Release objects in newList and oldList
}

Object* ProxyControl::createProxy(NPObject* object, const Reflect::Type type)
{
    if (!object)
    {
        return 0;
    }

    std::string className = getInterfaceName(npp, object);
    if (className == "Object")
    {
        // TODO: We should define 'Object' interface
        return 0;
    }

    bool usedHint = false;
    for (;;)
    {
        std::map<const std::string, Object* (*)(ProxyObject object)>::iterator it;
        it = proxyConstructorMap.find(className);
        if (it != proxyConstructorMap.end())
        {
            ProxyObject browserObject(object, npp);
            if (Object* object = (*it).second(browserObject))
            {
                return track(object);
            }
        }
        if (!type.isObject() || usedHint)
        {
            break;
        }
        className = type.getQualifiedName();
        size_t pos = className.rfind(':');
        if (pos != std::string::npos)
        {
            className = className.substr(pos + 1);
            printf("%s: use the class name '%s' as hinted.\n", __func__, className.c_str());
        }
        usedHint = true;
    }
    return 0;
}

long ProxyControl::enter()
{
    return ++nestingCount;
}

long ProxyControl::leave()
{
    --nestingCount;
    assert(0 <= nestingCount);
    if (nestingCount == 0)
    {
        while (!newList.empty())
        {
            Object* object = newList.front();
            newList.pop_front();
            if (0 < object->release())
            {
                oldList.push_back(object);
            }
        }
    }
    return nestingCount;
}

void ProxyControl::registerMetaData(const char* meta, Object* (*createProxy)(ProxyObject object), const char* alias)
{
    Reflect::Interface interface(meta);
    std::string name = interface.getName();
    if (alias)
    {
        name = alias;
    }
    proxyConstructorMap[name] = createProxy;
    printf("%s\n", name.c_str());
}

ProxyObject::ProxyObject(NPObject* object, NPP npp) :
    object(object),
    npp(npp),
    count(0)
{
}

ProxyObject::ProxyObject(const ProxyObject& original) :
    object(original.object),
    npp(original.npp),
    count(original.count)
{
}

ProxyObject::~ProxyObject()
{
    // TODO: Remove this from newList or oldList is it is still included
}

unsigned int ProxyObject::retain()
{
    NPN_RetainObject(object);
    return ++count;
}

unsigned int ProxyObject::release()
{
    if (0 < count)
    {
        NPN_ReleaseObject(object);
        --count;
    }
    if (count == 0)
    {
        delete this;
        return 0;
    }
    return count;
}

unsigned int ProxyObject::mark()
{
    return ++count;
}

PluginInstance::PluginInstance(NPP npp, NPObject* window) :
    proxyControl(npp),
    stubControl(npp),
    window(0)
{
    npp->pdata = this;
    this->window = interface_cast<org::w3c::dom::html::Window*>(proxyControl.createProxy(window, Reflect::Type("O14::html::Window")));
    if (this->window)
    {
        ProxyObject* proxy = interface_cast<ProxyObject*>(this->window);
        proxy->mark();
        proxy->retain();
    }
}

PluginInstance::~PluginInstance()
{
    if (window)
    {
        window->release();
    }
}

<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "include/types.h"
#include "WorkQueue.h"

#include "common/config.h"

#define DOUT_SUBSYS tp
#undef dout_prefix
#define dout_prefix *_dout << name << " "

void ThreadPool::worker()
{
  _lock.Lock();
  ldout(cct,10) << "worker start" << dendl;
  while (!_stop) {
    if (!_pause && work_queues.size()) {
      WorkQueue_* wq;
      int tries = work_queues.size();
      bool did = false;
      while (tries--) {
	last_work_queue++;
	last_work_queue %= work_queues.size();
	wq = work_queues[last_work_queue];

	void *item = wq->_void_dequeue();
	if (item) {
	  processing++;
	  ldout(cct,12) << "worker wq " << wq->name << " start processing " << item << dendl;
	  _lock.Unlock();
	  wq->_void_process(item);
	  _lock.Lock();
	  wq->_void_process_finish(item);
	  ldout(cct,15) << "worker wq " << wq->name << " done processing " << item << dendl;
	  processing--;
	  if (_pause || _draining)
	    _wait_cond.Signal();
	  did = true;
	  break;
	}
      }
      if (did)
	continue;
    }
    ldout(cct,15) << "worker waiting" << dendl;
    _cond.Wait(_lock);
  }
  ldout(cct,0) << "worker finish" << dendl;
  _lock.Unlock();
}

void ThreadPool::start()
{
  ldout(cct,10) << "start" << dendl;
  for (set<WorkThread*>::iterator p = _threads.begin();
       p != _threads.end();
       p++)
    (*p)->create();
  ldout(cct,15) << "started" << dendl;
}
void ThreadPool::stop(bool clear_after)
{
  ldout(cct,10) << "stop" << dendl;
  _lock.Lock();
  _stop = true;
  _cond.Signal();
  _lock.Unlock();
  for (set<WorkThread*>::iterator p = _threads.begin();
       p != _threads.end();
       p++)
    (*p)->join();
  _lock.Lock();
  for (unsigned i=0; i<work_queues.size(); i++)
    work_queues[i]->_clear();
  _lock.Unlock();
  ldout(cct,15) << "stopped" << dendl;
}

void ThreadPool::pause()
{
  ldout(cct,10) << "pause" << dendl;
  _lock.Lock();
  assert(!_pause);
  _pause = true;
  while (processing)
    _wait_cond.Wait(_lock);
  _lock.Unlock();
  ldout(cct,15) << "paused" << dendl;
}

void ThreadPool::pause_new()
{
  ldout(cct,10) << "pause_new" << dendl;
  _lock.Lock();
  assert(!_pause);
  _pause = true;
  _lock.Unlock();
}

void ThreadPool::unpause()
{
  ldout(cct,10) << "unpause" << dendl;
  _lock.Lock();
  assert(_pause);
  _pause = false;
  _cond.Signal();
  _lock.Unlock();
}

void ThreadPool::drain(WorkQueue_* wq)
{
  ldout(cct,10) << "drain" << dendl;
  _lock.Lock();
  _draining++;
  while (processing || (wq != NULL && !wq->_empty()))
    _wait_cond.Wait(_lock);
  _draining--;
  _lock.Unlock();
}

<commit_msg>workqueue: register and time out worker threads<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sstream>

#include "include/types.h"
#include "include/utime.h"
#include "WorkQueue.h"

#include "common/config.h"
#include "common/HeartbeatMap.h"

#define DOUT_SUBSYS tp
#undef dout_prefix
#define dout_prefix *_dout << name << " "

void ThreadPool::worker()
{
  _lock.Lock();
  ldout(cct,10) << "worker start" << dendl;

  std::stringstream ss;
  ss << name << '@' << this;
  heartbeat_handle_d *hb = cct->get_heartbeat_map()->add_worker(pthread_self(), ss.str());

  while (!_stop) {
    if (!_pause && work_queues.size()) {
      WorkQueue_* wq;
      int tries = work_queues.size();
      bool did = false;
      while (tries--) {
	last_work_queue++;
	last_work_queue %= work_queues.size();
	wq = work_queues[last_work_queue];

	void *item = wq->_void_dequeue();
	if (item) {
	  processing++;
	  ldout(cct,12) << "worker wq " << wq->name << " start processing " << item << dendl;
	  _lock.Unlock();
	  cct->get_heartbeat_map()->touch_worker(hb, wq->timeout_interval);
	  wq->_void_process(item);
	  _lock.Lock();
	  wq->_void_process_finish(item);
	  ldout(cct,15) << "worker wq " << wq->name << " done processing " << item << dendl;
	  processing--;
	  if (_pause || _draining)
	    _wait_cond.Signal();
	  did = true;
	  break;
	}
      }
      if (did)
	continue;
    }

    ldout(cct,15) << "worker waiting" << dendl;
    cct->get_heartbeat_map()->touch_worker(hb, 4);
    _cond.WaitInterval(cct, _lock, utime_t(2, 0));
  }
  ldout(cct,0) << "worker finish" << dendl;

  cct->get_heartbeat_map()->remove_worker(hb);

  _lock.Unlock();
}

void ThreadPool::start()
{
  ldout(cct,10) << "start" << dendl;
  for (set<WorkThread*>::iterator p = _threads.begin();
       p != _threads.end();
       p++)
    (*p)->create();
  ldout(cct,15) << "started" << dendl;
}
void ThreadPool::stop(bool clear_after)
{
  ldout(cct,10) << "stop" << dendl;
  _lock.Lock();
  _stop = true;
  _cond.Signal();
  _lock.Unlock();
  for (set<WorkThread*>::iterator p = _threads.begin();
       p != _threads.end();
       p++)
    (*p)->join();
  _lock.Lock();
  for (unsigned i=0; i<work_queues.size(); i++)
    work_queues[i]->_clear();
  _lock.Unlock();
  ldout(cct,15) << "stopped" << dendl;
}

void ThreadPool::pause()
{
  ldout(cct,10) << "pause" << dendl;
  _lock.Lock();
  assert(!_pause);
  _pause = true;
  while (processing)
    _wait_cond.Wait(_lock);
  _lock.Unlock();
  ldout(cct,15) << "paused" << dendl;
}

void ThreadPool::pause_new()
{
  ldout(cct,10) << "pause_new" << dendl;
  _lock.Lock();
  assert(!_pause);
  _pause = true;
  _lock.Unlock();
}

void ThreadPool::unpause()
{
  ldout(cct,10) << "unpause" << dendl;
  _lock.Lock();
  assert(_pause);
  _pause = false;
  _cond.Signal();
  _lock.Unlock();
}

void ThreadPool::drain(WorkQueue_* wq)
{
  ldout(cct,10) << "drain" << dendl;
  _lock.Lock();
  _draining++;
  while (processing || (wq != NULL && !wq->_empty()))
    _wait_cond.Wait(_lock);
  _draining--;
  _lock.Unlock();
}

<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mabstractitemmodel.h"
#include "mabstractitemmodel_p.h"

MAbstractItemModelPrivate::MAbstractItemModelPrivate()
    : q_ptr(0), groupMode(false)
{
}

MAbstractItemModelPrivate::~MAbstractItemModelPrivate()
{
}

void MAbstractItemModelPrivate::connectModel()
{
    Q_Q(MAbstractItemModel);

    connect(q, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(_q_rowsInsertAnimated(QModelIndex,int,int)));
    connect(q, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(_q_rowsRemoveAnimated(QModelIndex,int,int)));
}

void MAbstractItemModelPrivate::setGrouped(bool mode)
{
    groupMode = mode;
}

bool MAbstractItemModelPrivate::isGrouped() const
{
    return groupMode;
}

void MAbstractItemModelPrivate::setChangeAnimated(bool animated)
{
    animatedChange.push(animated);
}

bool MAbstractItemModelPrivate::changeAnimated()
{
    return animatedChange.pop();
}

void MAbstractItemModelPrivate::_q_rowsInsertAnimated(const QModelIndex &parent, int first, int last)
{
    Q_Q(MAbstractItemModel);

    emit q->rowsInserted(parent, first, last, changeAnimated());
}

void MAbstractItemModelPrivate::_q_rowsRemoveAnimated(const QModelIndex &parent, int first, int last)
{
    Q_Q(MAbstractItemModel);

    emit q->rowsRemoved(parent, first, last, changeAnimated());
}

MAbstractItemModel::MAbstractItemModel(QObject *parent)
    : QAbstractItemModel(parent),
    d_ptr(new MAbstractItemModelPrivate)
{
    Q_D(MAbstractItemModel);

    d->q_ptr = this;
    d->connectModel();
}

MAbstractItemModel::~MAbstractItemModel()
{
    delete d_ptr;
}

void MAbstractItemModel::setGrouped(bool mode)
{
    Q_D(MAbstractItemModel);

    if (d->isGrouped() == mode)
        return;

    d->setGrouped(mode);
    emit layoutChanged();
}

bool MAbstractItemModel::isGrouped() const
{
    Q_D(const MAbstractItemModel);

    return d->isGrouped();
}

int MAbstractItemModel::rowCount(const QModelIndex &parent) const
{
    if (isGrouped()) {
        if (parent.isValid())
            return rowCountInGroup(parent.row());
        else
            return groupCount();
    } else {
        if (parent.isValid())
            return 0;
        else
            return rowCountInGroup(-1);
    }
}

QModelIndex MAbstractItemModel::index(int row, int column, const QModelIndex &parent) const
{
    return row < rowCountInGroup(parent.row()) ? createIndex(row, column, parent.row()) : QModelIndex();
}

QModelIndex MAbstractItemModel::parent(const QModelIndex &child) const
{
    if (isGrouped()) {
        return index(child.internalId(), 0);
    }

    return QModelIndex();
}

int MAbstractItemModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return 1;
}

QVariant MAbstractItemModel::data(const QModelIndex &index, int role) const
{
    if (isGrouped()) {
        if (!index.parent().isValid())
            return groupTitle(index.row());
        else
            return itemData(index.row(), index.parent().row(), role);
    } else {
        if (index.isValid())
            return itemData(index.row(), -1, role);
    }

    return QVariant();
}

void MAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last, bool animated)
{
    Q_D(MAbstractItemModel);

    QAbstractItemModel::beginInsertRows(parent, first, last);
    d->setChangeAnimated(animated);
}

void MAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last, bool animated)
{
    Q_D(MAbstractItemModel);

    QAbstractItemModel::beginRemoveRows(parent, first, last);
    d->setChangeAnimated(animated);
}
<commit_msg>Fixes: NB#206584 - MAbstractItemModel was returning an invalid parent index.<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mabstractitemmodel.h"
#include "mabstractitemmodel_p.h"

MAbstractItemModelPrivate::MAbstractItemModelPrivate()
    : q_ptr(0), groupMode(false)
{
}

MAbstractItemModelPrivate::~MAbstractItemModelPrivate()
{
}

void MAbstractItemModelPrivate::connectModel()
{
    Q_Q(MAbstractItemModel);

    connect(q, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(_q_rowsInsertAnimated(QModelIndex,int,int)));
    connect(q, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(_q_rowsRemoveAnimated(QModelIndex,int,int)));
}

void MAbstractItemModelPrivate::setGrouped(bool mode)
{
    groupMode = mode;
}

bool MAbstractItemModelPrivate::isGrouped() const
{
    return groupMode;
}

void MAbstractItemModelPrivate::setChangeAnimated(bool animated)
{
    animatedChange.push(animated);
}

bool MAbstractItemModelPrivate::changeAnimated()
{
    return animatedChange.pop();
}

void MAbstractItemModelPrivate::_q_rowsInsertAnimated(const QModelIndex &parent, int first, int last)
{
    Q_Q(MAbstractItemModel);

    emit q->rowsInserted(parent, first, last, changeAnimated());
}

void MAbstractItemModelPrivate::_q_rowsRemoveAnimated(const QModelIndex &parent, int first, int last)
{
    Q_Q(MAbstractItemModel);

    emit q->rowsRemoved(parent, first, last, changeAnimated());
}

MAbstractItemModel::MAbstractItemModel(QObject *parent)
    : QAbstractItemModel(parent),
    d_ptr(new MAbstractItemModelPrivate)
{
    Q_D(MAbstractItemModel);

    d->q_ptr = this;
    d->connectModel();
}

MAbstractItemModel::~MAbstractItemModel()
{
    delete d_ptr;
}

void MAbstractItemModel::setGrouped(bool mode)
{
    Q_D(MAbstractItemModel);

    if (d->isGrouped() == mode)
        return;

    d->setGrouped(mode);
    emit layoutChanged();
}

bool MAbstractItemModel::isGrouped() const
{
    Q_D(const MAbstractItemModel);

    return d->isGrouped();
}

int MAbstractItemModel::rowCount(const QModelIndex &parent) const
{
    if (isGrouped()) {
        if (parent.isValid())
            return rowCountInGroup(parent.row());
        else
            return groupCount();
    } else {
        if (parent.isValid())
            return 0;
        else
            return rowCountInGroup(-1);
    }
}

QModelIndex MAbstractItemModel::index(int row, int column, const QModelIndex &parent) const
{
    return (row >= 0 && row < rowCountInGroup(parent.row())) ? createIndex(row, column, parent.row()) : QModelIndex();
}

QModelIndex MAbstractItemModel::parent(const QModelIndex &child) const
{
    if (isGrouped()) {
        return index(child.internalId(), 0);
    }

    return QModelIndex();
}

int MAbstractItemModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return 1;
}

QVariant MAbstractItemModel::data(const QModelIndex &index, int role) const
{
    if (isGrouped()) {
        if (!index.parent().isValid())
            return groupTitle(index.row());
        else
            return itemData(index.row(), index.parent().row(), role);
    } else {
        if (index.isValid())
            return itemData(index.row(), -1, role);
    }

    return QVariant();
}

void MAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last, bool animated)
{
    Q_D(MAbstractItemModel);

    QAbstractItemModel::beginInsertRows(parent, first, last);
    d->setChangeAnimated(animated);
}

void MAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last, bool animated)
{
    Q_D(MAbstractItemModel);

    QAbstractItemModel::beginRemoveRows(parent, first, last);
    d->setChangeAnimated(animated);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015, The Monero Project
//
// 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.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
//    used to endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers

#include "checkpoints_create.h"
#include "common/dns_utils.h"
#include "include_base_utils.h"
#include <sstream>
#include <random>
#include "storages/portable_storage_template_helper.h" // epee json include

namespace cryptonote
{

struct t_hashline
{
	uint64_t height;
	std::string hash;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(height)
        KV_SERIALIZE(hash)
      END_KV_SERIALIZE_MAP()
};

struct t_hash_json {
 	std::vector<t_hashline> hashlines;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(hashlines)
      END_KV_SERIALIZE_MAP()
};

bool create_checkpoints(cryptonote::checkpoints& checkpoints)
{
  ADD_CHECKPOINT(1,     "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
  ADD_CHECKPOINT(10,    "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
  ADD_CHECKPOINT(100,   "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
  ADD_CHECKPOINT(1000,  "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876");
  ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2");
  ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
  ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
  ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
  ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
  ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
  ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2");
  ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb");
  ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063");
  ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553");
  ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61");
  ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf");
  ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131");
  ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8");
  ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d");

  return true;
}

bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  boost::system::error_code errcode;
  if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
  {
    LOG_PRINT_L1("Blockchain checkpoints file not found");
    return true;
  }

  LOG_PRINT_L1("Adding checkpoints from blockchain hashfile");

  uint64_t prev_max_height = checkpoints.get_max_height();
  LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
  t_hash_json hashes;
  epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
  for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
  {
      uint64_t height;
      height = it->height;
      if (height <= prev_max_height) {
	LOG_PRINT_L1("ignoring checkpoint height " << height);
      } else {
	std::string blockhash = it->hash;
	LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
	ADD_CHECKPOINT(height, blockhash);
      }
      ++it;
  }

  return true;
}

bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints)
{
  // All four MoneroPulse domains have DNSSEC on and valid
  static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
						   , "checkpoints.moneropulse.org"
						   , "checkpoints.moneropulse.net"
						   , "checkpoints.moneropulse.co"
  };
  bool avail, valid;
  std::vector<std::string> records;

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
  size_t first_index = dis(gen);

  size_t cur_index = first_index;
  do
  {
    records = tools::DNSResolver::instance().get_txt_record(dns_urls[cur_index], avail, valid);
    if (records.size() == 0 || (avail && !valid))
    {
      cur_index++;
      if (cur_index == dns_urls.size())
      {
	cur_index = 0;
      }
      continue;
    }
    break;
  } while (cur_index != first_index);

  if (records.size() == 0)
  {
    LOG_PRINT_L1("Fetching MoneroPulse checkpoints failed, no TXT records available.");
    return true;
  }

  if (avail && !valid)
  {
    LOG_PRINT_L0("WARNING: MoneroPulse failed DNSSEC validation and/or returned no records");
    return true;
  }

  for (auto& record : records)
  {
    auto pos = record.find(":");
    if (pos != std::string::npos)
    {
      uint64_t height;
      crypto::hash hash;

      // parse the first part as uint64_t,
      // if this fails move on to the next record
      std::stringstream ss(record.substr(0, pos));
      if (!(ss >> height))
      {
	continue;
      }

      // parse the second part as crypto::hash,
      // if this fails move on to the next record
      std::string hashStr = record.substr(pos + 1);
      if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
      {
	continue;
      }

      ADD_CHECKPOINT(height, hashStr);
    }
  }
  return true;
}

bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  // TODO: replace hard-coded url with const string or #define
  return (load_checkpoints_from_json(checkpoints, json_hashfile_fullpath) && load_checkpoints_from_dns(checkpoints));
}

}  // namespace cryptonote
<commit_msg>update checkpoint<commit_after>// Copyright (c) 2014-2015, The Monero Project
//
// 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.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
//    used to endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers

#include "checkpoints_create.h"
#include "common/dns_utils.h"
#include "include_base_utils.h"
#include <sstream>
#include <random>
#include "storages/portable_storage_template_helper.h" // epee json include

namespace cryptonote
{

struct t_hashline
{
	uint64_t height;
	std::string hash;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(height)
        KV_SERIALIZE(hash)
      END_KV_SERIALIZE_MAP()
};

struct t_hash_json {
 	std::vector<t_hashline> hashlines;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(hashlines)
      END_KV_SERIALIZE_MAP()
};

bool create_checkpoints(cryptonote::checkpoints& checkpoints)
{
  ADD_CHECKPOINT(1,     "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
  ADD_CHECKPOINT(10,    "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
  ADD_CHECKPOINT(100,   "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
  ADD_CHECKPOINT(1000,  "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876");
  ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2");
  ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
  ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
  ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
  ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
  ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
  ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2");
  ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb");
  ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063");
  ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553");
  ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61");
  ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf");
  ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131");
  ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8");
  ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d");
  ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831");

  return true;
}

bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  boost::system::error_code errcode;
  if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
  {
    LOG_PRINT_L1("Blockchain checkpoints file not found");
    return true;
  }

  LOG_PRINT_L1("Adding checkpoints from blockchain hashfile");

  uint64_t prev_max_height = checkpoints.get_max_height();
  LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
  t_hash_json hashes;
  epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
  for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
  {
      uint64_t height;
      height = it->height;
      if (height <= prev_max_height) {
	LOG_PRINT_L1("ignoring checkpoint height " << height);
      } else {
	std::string blockhash = it->hash;
	LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
	ADD_CHECKPOINT(height, blockhash);
      }
      ++it;
  }

  return true;
}

bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints)
{
  // All four MoneroPulse domains have DNSSEC on and valid
  static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
						   , "checkpoints.moneropulse.org"
						   , "checkpoints.moneropulse.net"
						   , "checkpoints.moneropulse.co"
  };
  bool avail, valid;
  std::vector<std::string> records;

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
  size_t first_index = dis(gen);

  size_t cur_index = first_index;
  do
  {
    records = tools::DNSResolver::instance().get_txt_record(dns_urls[cur_index], avail, valid);
    if (records.size() == 0 || (avail && !valid))
    {
      cur_index++;
      if (cur_index == dns_urls.size())
      {
	cur_index = 0;
      }
      continue;
    }
    break;
  } while (cur_index != first_index);

  if (records.size() == 0)
  {
    LOG_PRINT_L1("Fetching MoneroPulse checkpoints failed, no TXT records available.");
    return true;
  }

  if (avail && !valid)
  {
    LOG_PRINT_L0("WARNING: MoneroPulse failed DNSSEC validation and/or returned no records");
    return true;
  }

  for (auto& record : records)
  {
    auto pos = record.find(":");
    if (pos != std::string::npos)
    {
      uint64_t height;
      crypto::hash hash;

      // parse the first part as uint64_t,
      // if this fails move on to the next record
      std::stringstream ss(record.substr(0, pos));
      if (!(ss >> height))
      {
	continue;
      }

      // parse the second part as crypto::hash,
      // if this fails move on to the next record
      std::string hashStr = record.substr(pos + 1);
      if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
      {
	continue;
      }

      ADD_CHECKPOINT(height, hashStr);
    }
  }
  return true;
}

bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  // TODO: replace hard-coded url with const string or #define
  return (load_checkpoints_from_json(checkpoints, json_hashfile_fullpath) && load_checkpoints_from_dns(checkpoints));
}

}  // namespace cryptonote
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2019, The OpenThread Authors.
 *  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.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 */

/**
 * @file
 *   This file includes definitions for NCP service.
 */

#ifndef OTBR_COMMON_OTBR_MAINLOOP_HPP_
#define OTBR_COMMON_OTBR_MAINLOOP_HPP_

#include <openthread-br/config.h>

#include <openthread/openthread-system.h>

namespace otbr {

/**
 * This type defines the mainloop context that contains context data
 * for running a mainloop.
 *
 */
using MainloopContext = otSysMainloopContext;

/**
 * This abstract class defines the interface of a mainloop processor
 * which add fds to the mainloop context and handle fd events.
 *
 */
class MainloopProcessor
{
public:
    virtual ~MainloopProcessor(void) = default;

    /**
     * This method updates the mainloop context.
     *
     * @param[inout]  aMainloop  A reference to the mainloop to be updated.
     *
     */
    virtual void Update(MainloopContext &aMainloop) = 0;

    /**
     * This method processes mainloop events.
     *
     * @param[in]  aMainloop  A reference to the mainloop context.
     *
     */
    virtual void Process(const MainloopContext &aMainloop) = 0;
};

} // namespace otbr

#endif // OTBR_COMMON_OTBR_MAINLOOP_HPP_
<commit_msg>[docs] fix typos in mainloop.hpp (#962)<commit_after>/*
 *  Copyright (c) 2019, The OpenThread Authors.
 *  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.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 */

/**
 * @file
 *   This file includes definitions for mainloop processor.
 */

#ifndef OTBR_COMMON_OTBR_MAINLOOP_HPP_
#define OTBR_COMMON_OTBR_MAINLOOP_HPP_

#include <openthread-br/config.h>

#include <openthread/openthread-system.h>

namespace otbr {

/**
 * This type defines the context data for running a mainloop.
 *
 */
using MainloopContext = otSysMainloopContext;

/**
 * This abstract class defines the interface of a mainloop processor
 * which adds fds to the mainloop context and handles fds events.
 *
 */
class MainloopProcessor
{
public:
    virtual ~MainloopProcessor(void) = default;

    /**
     * This method updates the mainloop context.
     *
     * @param[inout]  aMainloop  A reference to the mainloop to be updated.
     *
     */
    virtual void Update(MainloopContext &aMainloop) = 0;

    /**
     * This method processes mainloop events.
     *
     * @param[in]  aMainloop  A reference to the mainloop context.
     *
     */
    virtual void Process(const MainloopContext &aMainloop) = 0;
};

} // namespace otbr

#endif // OTBR_COMMON_OTBR_MAINLOOP_HPP_
<|endoftext|>


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

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
#include "grit/content_resources.h"
#include "mojo/public/cpp/bindings/allocation_scope.h"
#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/js/bindings/constants.h"

namespace content {
namespace {

bool got_message = false;
int message_count = 0;

const int kExpectedMessageCount = 1000;

// Positive numbers with different values in each byte, the last of
// which can survive promotion to double and back.
const int8  kExpectedInt8Value = 65;
const int16 kExpectedInt16Value = 16961;
const int32 kExpectedInt32Value = 1145258561;
const int64 kExpectedInt64Value = 77263311946305LL;

// Returns the path to the mojom js bindings file.
base::FilePath GetFilePathForJSResource(const std::string& path) {
  std::string binding_path = "gen/" + path + ".js";
#if defined(OS_WIN)
  std::string tmp;
  base::ReplaceChars(binding_path, "//", "\\", &tmp);
  binding_path.swap(tmp);
#endif
  base::FilePath file_path;
  PathService::Get(CHILD_PROCESS_EXE, &file_path);
  return file_path.DirName().AppendASCII(binding_path);
}

// The bindings for the page are generated from a .mojom file. This code looks
// up the generated file from disk and returns it.
bool GetResource(const std::string& id,
                 const WebUIDataSource::GotDataCallback& callback) {
  // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
  if (id == mojo::kCodecModuleName ||
      id == mojo::kConnectionModuleName ||
      id == mojo::kConnectorModuleName ||
      id == mojo::kRouterModuleName)
    return false;

  std::string contents;
  CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents,
                               std::string::npos)) << id;
  base::RefCountedString* ref_contents = new base::RefCountedString;
  ref_contents->data() = contents;
  callback.Run(ref_contents);
  return true;
}

class BrowserTargetImpl : public mojo::BrowserTarget {
 public:
  BrowserTargetImpl(mojo::ScopedRendererTargetHandle& handle,
                    base::RunLoop* run_loop)
      : client_(handle.Pass(), this),
        run_loop_(run_loop) {
  }

  virtual ~BrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  virtual void PingResponse() OVERRIDE {
    NOTREACHED();
  }

  virtual void EchoResponse(const mojo::EchoArgs& arg1,
                            const mojo::EchoArgs& arg2) OVERRIDE {
    NOTREACHED();
  }

 protected:
  mojo::RemotePtr<mojo::RendererTarget> client_;
  base::RunLoop* run_loop_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
};

class PingBrowserTargetImpl : public BrowserTargetImpl {
 public:
  PingBrowserTargetImpl(mojo::ScopedRendererTargetHandle handle,
                        base::RunLoop* run_loop)
      : BrowserTargetImpl(handle, run_loop) {
    client_->Ping();
  }

  virtual ~PingBrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  // Quit the RunLoop when called.
  virtual void PingResponse() OVERRIDE {
    got_message = true;
    run_loop_->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(PingBrowserTargetImpl);
};

class EchoBrowserTargetImpl : public BrowserTargetImpl {
 public:
  EchoBrowserTargetImpl(mojo::ScopedRendererTargetHandle handle,
                        base::RunLoop* run_loop)
      : BrowserTargetImpl(handle, run_loop) {
    mojo::AllocationScope scope;
    mojo::EchoArgs::Builder builder;
    builder.set_w(kExpectedInt64Value);
    builder.set_x(kExpectedInt32Value);
    builder.set_y(kExpectedInt16Value);
    builder.set_z(kExpectedInt8Value);
    builder.set_name("coming");
    client_->Echo(builder.Finish());
  }

  virtual ~EchoBrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  // Check the response, and quit the RunLoop after N calls.
  virtual void EchoResponse(const mojo::EchoArgs& arg1,
                            const mojo::EchoArgs& arg2) OVERRIDE {
    EXPECT_EQ(kExpectedInt64Value, arg1.w());
    EXPECT_EQ(kExpectedInt32Value, arg1.x());
    EXPECT_EQ(kExpectedInt16Value, arg1.y());
    EXPECT_EQ(kExpectedInt8Value, arg1.z());
    EXPECT_EQ(std::string("coming"), arg1.name().To<std::string>());

    EXPECT_EQ(-1LL, arg2.w());
    EXPECT_EQ(-1, arg2.x());
    EXPECT_EQ(-1, arg2.y());
    EXPECT_EQ(-1, arg2.z());
    EXPECT_EQ(std::string("going"), arg2.name().To<std::string>());

    message_count += 1;
    if (message_count == kExpectedMessageCount)
      run_loop_->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(EchoBrowserTargetImpl);
};

// WebUIController that sets up mojo bindings.
class TestWebUIController : public WebUIController {
 public:
   TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
      : WebUIController(web_ui),
        run_loop_(run_loop) {
    content::WebUIDataSource* data_source =
        WebUIDataSource::AddMojoDataSource(
            web_ui->GetWebContents()->GetBrowserContext());
    data_source->SetRequestFilter(base::Bind(&GetResource));
  }

 protected:
  base::RunLoop* run_loop_;
  scoped_ptr<BrowserTargetImpl> browser_target_;

 private:
  DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
};

// TestWebUIController that additionally creates the ping test BrowserTarget
// implementation at the right time.
class PingTestWebUIController : public TestWebUIController {
 public:
   PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
       : TestWebUIController(web_ui, run_loop) {
   }

  // WebUIController overrides:
  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
    mojo::InterfacePipe<mojo::BrowserTarget, mojo::RendererTarget> pipe;
    browser_target_.reset(new PingBrowserTargetImpl(
        pipe.handle_to_peer.Pass(), run_loop_));
    render_view_host->SetWebUIHandle(
        mojo::ScopedMessagePipeHandle(pipe.handle_to_self.release()));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
};

// TestWebUIController that additionally creates the echo test BrowserTarget
// implementation at the right time.
class EchoTestWebUIController : public TestWebUIController {
 public:
   EchoTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
      : TestWebUIController(web_ui, run_loop) {
  }

  // WebUIController overrides:
  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
    mojo::InterfacePipe<mojo::BrowserTarget, mojo::RendererTarget> pipe;
    browser_target_.reset(new EchoBrowserTargetImpl(
        pipe.handle_to_peer.Pass(), run_loop_));
    render_view_host->SetWebUIHandle(
        mojo::ScopedMessagePipeHandle(pipe.handle_to_self.release()));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(EchoTestWebUIController);
};

// WebUIControllerFactory that creates TestWebUIController.
class TestWebUIControllerFactory : public WebUIControllerFactory {
 public:
  TestWebUIControllerFactory() : run_loop_(NULL) {}

  void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }

  virtual WebUIController* CreateWebUIControllerForURL(
      WebUI* web_ui, const GURL& url) const OVERRIDE {
    if (url.query() == "ping")
      return new PingTestWebUIController(web_ui, run_loop_);
    if (url.query() == "echo")
      return new EchoTestWebUIController(web_ui, run_loop_);
    return NULL;
  }
  virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
      const GURL& url) const OVERRIDE {
    return reinterpret_cast<WebUI::TypeID>(1);
  }
  virtual bool UseWebUIForURL(BrowserContext* browser_context,
                              const GURL& url) const OVERRIDE {
    return true;
  }
  virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
                                      const GURL& url) const OVERRIDE {
    return true;
  }

 private:
  base::RunLoop* run_loop_;

  DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
};

class WebUIMojoTest : public ContentBrowserTest {
 public:
  WebUIMojoTest() {
    WebUIControllerFactory::RegisterFactory(&factory_);
  }

  virtual ~WebUIMojoTest() {
    WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
  }

  TestWebUIControllerFactory* factory() { return &factory_; }

 private:
  TestWebUIControllerFactory factory_;

  DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
};

// Loads a webui page that contains mojo bindings and verifies a message makes
// it from the browser to the page and back.
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, DISABLED_EndToEndPing) {
  // Currently there is no way to have a generated file included in the isolate
  // files. If the bindings file doesn't exist assume we're on such a bot and
  // pass.
  // TODO(sky): remove this conditional when isolates support copying from gen.
  const base::FilePath test_file_path(
      GetFilePathForJSResource(
          "content/test/data/web_ui_test_mojo_bindings.mojom"));
  if (!base::PathExists(test_file_path)) {
    LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
    return;
  }

  got_message = false;
  ASSERT_TRUE(test_server()->Start());
  base::RunLoop run_loop;
  factory()->set_run_loop(&run_loop);
  GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?ping"));
  NavigateToURL(shell(), test_url);
  // RunLoop is quit when message received from page.
  run_loop.Run();
  EXPECT_TRUE(got_message);
}

// Loads a webui page that contains mojo bindings and verifies that
// parameters are passed back correctly from JavaScript.
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, DISABLED_EndToEndEcho) {
  // Currently there is no way to have a generated file included in the isolate
  // files. If the bindings file doesn't exist assume we're on such a bot and
  // pass.
  // TODO(sky): remove this conditional when isolates support copying from gen.
  const base::FilePath test_file_path(
      GetFilePathForJSResource(
          "content/test/data/web_ui_test_mojo_bindings.mojom"));
  if (!base::PathExists(test_file_path)) {
    LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
    return;
  }

  message_count = 0;
  ASSERT_TRUE(test_server()->Start());
  base::RunLoop run_loop;
  factory()->set_run_loop(&run_loop);
  GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?echo"));
  NavigateToURL(shell(), test_url);
  // RunLoop is quit when response received from page.
  run_loop.Run();
  EXPECT_EQ(kExpectedMessageCount, message_count);
}

}  // namespace
}  // namespace content
<commit_msg>Revert "Disabling content_browsertests WebUIMojoTest.EndToEndEcho, Ping"<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
#include "grit/content_resources.h"
#include "mojo/public/cpp/bindings/allocation_scope.h"
#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/js/bindings/constants.h"

namespace content {
namespace {

bool got_message = false;
int message_count = 0;

const int kExpectedMessageCount = 1000;

// Positive numbers with different values in each byte, the last of
// which can survive promotion to double and back.
const int8  kExpectedInt8Value = 65;
const int16 kExpectedInt16Value = 16961;
const int32 kExpectedInt32Value = 1145258561;
const int64 kExpectedInt64Value = 77263311946305LL;

// Returns the path to the mojom js bindings file.
base::FilePath GetFilePathForJSResource(const std::string& path) {
  std::string binding_path = "gen/" + path + ".js";
#if defined(OS_WIN)
  std::string tmp;
  base::ReplaceChars(binding_path, "//", "\\", &tmp);
  binding_path.swap(tmp);
#endif
  base::FilePath file_path;
  PathService::Get(CHILD_PROCESS_EXE, &file_path);
  return file_path.DirName().AppendASCII(binding_path);
}

// The bindings for the page are generated from a .mojom file. This code looks
// up the generated file from disk and returns it.
bool GetResource(const std::string& id,
                 const WebUIDataSource::GotDataCallback& callback) {
  // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
  if (id == mojo::kCodecModuleName ||
      id == mojo::kConnectionModuleName ||
      id == mojo::kConnectorModuleName ||
      id == mojo::kRouterModuleName)
    return false;

  std::string contents;
  CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents,
                               std::string::npos)) << id;
  base::RefCountedString* ref_contents = new base::RefCountedString;
  ref_contents->data() = contents;
  callback.Run(ref_contents);
  return true;
}

class BrowserTargetImpl : public mojo::BrowserTarget {
 public:
  BrowserTargetImpl(mojo::ScopedRendererTargetHandle& handle,
                    base::RunLoop* run_loop)
      : client_(handle.Pass(), this),
        run_loop_(run_loop) {
  }

  virtual ~BrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  virtual void PingResponse() OVERRIDE {
    NOTREACHED();
  }

  virtual void EchoResponse(const mojo::EchoArgs& arg1,
                            const mojo::EchoArgs& arg2) OVERRIDE {
    NOTREACHED();
  }

 protected:
  mojo::RemotePtr<mojo::RendererTarget> client_;
  base::RunLoop* run_loop_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
};

class PingBrowserTargetImpl : public BrowserTargetImpl {
 public:
  PingBrowserTargetImpl(mojo::ScopedRendererTargetHandle handle,
                        base::RunLoop* run_loop)
      : BrowserTargetImpl(handle, run_loop) {
    client_->Ping();
  }

  virtual ~PingBrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  // Quit the RunLoop when called.
  virtual void PingResponse() OVERRIDE {
    got_message = true;
    run_loop_->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(PingBrowserTargetImpl);
};

class EchoBrowserTargetImpl : public BrowserTargetImpl {
 public:
  EchoBrowserTargetImpl(mojo::ScopedRendererTargetHandle handle,
                        base::RunLoop* run_loop)
      : BrowserTargetImpl(handle, run_loop) {
    mojo::AllocationScope scope;
    mojo::EchoArgs::Builder builder;
    builder.set_w(kExpectedInt64Value);
    builder.set_x(kExpectedInt32Value);
    builder.set_y(kExpectedInt16Value);
    builder.set_z(kExpectedInt8Value);
    builder.set_name("coming");
    client_->Echo(builder.Finish());
  }

  virtual ~EchoBrowserTargetImpl() {}

  // mojo::BrowserTarget overrides:
  // Check the response, and quit the RunLoop after N calls.
  virtual void EchoResponse(const mojo::EchoArgs& arg1,
                            const mojo::EchoArgs& arg2) OVERRIDE {
    EXPECT_EQ(kExpectedInt64Value, arg1.w());
    EXPECT_EQ(kExpectedInt32Value, arg1.x());
    EXPECT_EQ(kExpectedInt16Value, arg1.y());
    EXPECT_EQ(kExpectedInt8Value, arg1.z());
    EXPECT_EQ(std::string("coming"), arg1.name().To<std::string>());

    EXPECT_EQ(-1LL, arg2.w());
    EXPECT_EQ(-1, arg2.x());
    EXPECT_EQ(-1, arg2.y());
    EXPECT_EQ(-1, arg2.z());
    EXPECT_EQ(std::string("going"), arg2.name().To<std::string>());

    message_count += 1;
    if (message_count == kExpectedMessageCount)
      run_loop_->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(EchoBrowserTargetImpl);
};

// WebUIController that sets up mojo bindings.
class TestWebUIController : public WebUIController {
 public:
   TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
      : WebUIController(web_ui),
        run_loop_(run_loop) {
    content::WebUIDataSource* data_source =
        WebUIDataSource::AddMojoDataSource(
            web_ui->GetWebContents()->GetBrowserContext());
    data_source->SetRequestFilter(base::Bind(&GetResource));
  }

 protected:
  base::RunLoop* run_loop_;
  scoped_ptr<BrowserTargetImpl> browser_target_;

 private:
  DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
};

// TestWebUIController that additionally creates the ping test BrowserTarget
// implementation at the right time.
class PingTestWebUIController : public TestWebUIController {
 public:
   PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
       : TestWebUIController(web_ui, run_loop) {
   }

  // WebUIController overrides:
  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
    mojo::InterfacePipe<mojo::BrowserTarget, mojo::RendererTarget> pipe;
    browser_target_.reset(new PingBrowserTargetImpl(
        pipe.handle_to_peer.Pass(), run_loop_));
    render_view_host->SetWebUIHandle(
        mojo::ScopedMessagePipeHandle(pipe.handle_to_self.release()));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
};

// TestWebUIController that additionally creates the echo test BrowserTarget
// implementation at the right time.
class EchoTestWebUIController : public TestWebUIController {
 public:
   EchoTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
      : TestWebUIController(web_ui, run_loop) {
  }

  // WebUIController overrides:
  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
    mojo::InterfacePipe<mojo::BrowserTarget, mojo::RendererTarget> pipe;
    browser_target_.reset(new EchoBrowserTargetImpl(
        pipe.handle_to_peer.Pass(), run_loop_));
    render_view_host->SetWebUIHandle(
        mojo::ScopedMessagePipeHandle(pipe.handle_to_self.release()));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(EchoTestWebUIController);
};

// WebUIControllerFactory that creates TestWebUIController.
class TestWebUIControllerFactory : public WebUIControllerFactory {
 public:
  TestWebUIControllerFactory() : run_loop_(NULL) {}

  void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }

  virtual WebUIController* CreateWebUIControllerForURL(
      WebUI* web_ui, const GURL& url) const OVERRIDE {
    if (url.query() == "ping")
      return new PingTestWebUIController(web_ui, run_loop_);
    if (url.query() == "echo")
      return new EchoTestWebUIController(web_ui, run_loop_);
    return NULL;
  }
  virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
      const GURL& url) const OVERRIDE {
    return reinterpret_cast<WebUI::TypeID>(1);
  }
  virtual bool UseWebUIForURL(BrowserContext* browser_context,
                              const GURL& url) const OVERRIDE {
    return true;
  }
  virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
                                      const GURL& url) const OVERRIDE {
    return true;
  }

 private:
  base::RunLoop* run_loop_;

  DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
};

class WebUIMojoTest : public ContentBrowserTest {
 public:
  WebUIMojoTest() {
    WebUIControllerFactory::RegisterFactory(&factory_);
  }

  virtual ~WebUIMojoTest() {
    WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
  }

  TestWebUIControllerFactory* factory() { return &factory_; }

 private:
  TestWebUIControllerFactory factory_;

  DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
};

// Temporarily disabled due to memory leaks. http://crbug.com/360081
#if defined(LEAK_SANITIZER)
#define MAYBE_EndToEndPing DISABLED_EndToEndPing
#define MAYBE_EndToEndEcho DISABLED_EndToEndEcho
#else
#define MAYBE_EndToEndPing EndToEndPing
#define MAYBE_EndToEndEcho EndToEndEcho
#endif

// Loads a webui page that contains mojo bindings and verifies a message makes
// it from the browser to the page and back.
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, MAYBE_EndToEndPing) {
  // Currently there is no way to have a generated file included in the isolate
  // files. If the bindings file doesn't exist assume we're on such a bot and
  // pass.
  // TODO(sky): remove this conditional when isolates support copying from gen.
  const base::FilePath test_file_path(
      GetFilePathForJSResource(
          "content/test/data/web_ui_test_mojo_bindings.mojom"));
  if (!base::PathExists(test_file_path)) {
    LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
    return;
  }

  got_message = false;
  ASSERT_TRUE(test_server()->Start());
  base::RunLoop run_loop;
  factory()->set_run_loop(&run_loop);
  GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?ping"));
  NavigateToURL(shell(), test_url);
  // RunLoop is quit when message received from page.
  run_loop.Run();
  EXPECT_TRUE(got_message);
}

// Loads a webui page that contains mojo bindings and verifies that
// parameters are passed back correctly from JavaScript.
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, MAYBE_EndToEndEcho) {
  // Currently there is no way to have a generated file included in the isolate
  // files. If the bindings file doesn't exist assume we're on such a bot and
  // pass.
  // TODO(sky): remove this conditional when isolates support copying from gen.
  const base::FilePath test_file_path(
      GetFilePathForJSResource(
          "content/test/data/web_ui_test_mojo_bindings.mojom"));
  if (!base::PathExists(test_file_path)) {
    LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
    return;
  }

  message_count = 0;
  ASSERT_TRUE(test_server()->Start());
  base::RunLoop run_loop;
  factory()->set_run_loop(&run_loop);
  GURL test_url(test_server()->GetURL("files/web_ui_mojo.html?echo"));
  NavigateToURL(shell(), test_url);
  // RunLoop is quit when response received from page.
  run_loop.Run();
  EXPECT_EQ(kExpectedMessageCount, message_count);
}

}  // namespace
}  // namespace content
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <assert.h>
#include <stdio.h>
#include "diagnosticsipc.h"

IpcStream::DiagnosticsIpc::DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength])
{
    memcpy(_pNamedPipeName, namedPipeName, sizeof(_pNamedPipeName));
}

IpcStream::DiagnosticsIpc::~DiagnosticsIpc()
{
    Close();
}

IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ErrorCallback callback)
{
    assert(pIpcName != nullptr);
    if (pIpcName == nullptr)
        return nullptr;

    char namedPipeName[MaxNamedPipeNameLength]{};
    const int nCharactersWritten = sprintf_s(
        namedPipeName,
        sizeof(namedPipeName),
        "\\\\.\\pipe\\%s-%d",
        pIpcName,
        ::GetCurrentProcessId());

    if (nCharactersWritten == -1)
    {
        if (callback != nullptr)
            callback("Failed to generate the named pipe name", nCharactersWritten);
        assert(nCharactersWritten != -1);
        return nullptr;
    }

    return new IpcStream::DiagnosticsIpc(namedPipeName);
}

IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const
{
    const uint32_t nInBufferSize = 16 * 1024;
    const uint32_t nOutBufferSize = 16 * 1024;
    HANDLE hPipe = ::CreateNamedPipeA(
        _pNamedPipeName,                                            // pipe name
        PIPE_ACCESS_DUPLEX,                                         // read/write access
        PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,    // message type pipe, message-read and blocking mode
        PIPE_UNLIMITED_INSTANCES,                                   // max. instances
        nOutBufferSize,                                             // output buffer size
        nInBufferSize,                                              // input buffer size
        0,                                                          // default client time-out
        NULL);                                                      // default security attribute

    if (hPipe == INVALID_HANDLE_VALUE)
    {
        if (callback != nullptr)
            callback("Failed to create an instance of a named pipe.", ::GetLastError());
        return nullptr;
    }

    const BOOL fSuccess = ::ConnectNamedPipe(hPipe, NULL) != 0;
    const DWORD errorCode = ::GetLastError();
    if (!fSuccess && (errorCode != ERROR_PIPE_CONNECTED))
    {
        if (callback != nullptr)
            callback("Failed to wait for a client process to connect.", errorCode);
        return nullptr;
    }

    return new IpcStream(hPipe);
}

void IpcStream::DiagnosticsIpc::Close(ErrorCallback)
{
}

IpcStream::~IpcStream()
{
    if (_hPipe != INVALID_HANDLE_VALUE)
    {
        Flush();

        const BOOL fSuccessDisconnectNamedPipe = ::DisconnectNamedPipe(_hPipe);
        assert(fSuccessDisconnectNamedPipe != 0);

        const BOOL fSuccessCloseHandle = ::CloseHandle(_hPipe);
        assert(fSuccessCloseHandle != 0);
    }
}

bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const
{
    assert(lpBuffer != nullptr);

    DWORD nNumberOfBytesRead = 0;
    const bool fSuccess = ::ReadFile(
        _hPipe,                 // handle to pipe
        lpBuffer,               // buffer to receive data
        nBytesToRead,           // size of buffer
        &nNumberOfBytesRead,    // number of bytes read
        NULL) != 0;             // not overlapped I/O

    if (!fSuccess)
    {
        // TODO: Add error handling.
    }

    nBytesRead = static_cast<uint32_t>(nNumberOfBytesRead);
    return fSuccess;
}

bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const
{
    assert(lpBuffer != nullptr);

    DWORD nNumberOfBytesWritten = 0;
    const bool fSuccess = ::WriteFile(
        _hPipe,                 // handle to pipe
        lpBuffer,               // buffer to write from
        nBytesToWrite,          // number of bytes to write
        &nNumberOfBytesWritten, // number of bytes written
        NULL) != 0;             // not overlapped I/O

    if (!fSuccess)
    {
        // TODO: Add error handling.
    }

    nBytesWritten = static_cast<uint32_t>(nNumberOfBytesWritten);
    return fSuccess;
}

bool IpcStream::Flush() const
{
    const bool fSuccess = ::FlushFileBuffers(_hPipe) != 0;
    if (!fSuccess)
    {
        // TODO: Add error handling.
    }
    return fSuccess;
}
<commit_msg>[Diagnostics Server][Windows] Close hPipe when a connection error occurred. (#25863)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <assert.h>
#include <stdio.h>
#include "diagnosticsipc.h"

IpcStream::DiagnosticsIpc::DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength])
{
    memcpy(_pNamedPipeName, namedPipeName, sizeof(_pNamedPipeName));
}

IpcStream::DiagnosticsIpc::~DiagnosticsIpc()
{
    Close();
}

IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ErrorCallback callback)
{
    assert(pIpcName != nullptr);
    if (pIpcName == nullptr)
        return nullptr;

    char namedPipeName[MaxNamedPipeNameLength]{};
    const int nCharactersWritten = sprintf_s(
        namedPipeName,
        sizeof(namedPipeName),
        "\\\\.\\pipe\\%s-%d",
        pIpcName,
        ::GetCurrentProcessId());

    if (nCharactersWritten == -1)
    {
        if (callback != nullptr)
            callback("Failed to generate the named pipe name", nCharactersWritten);
        assert(nCharactersWritten != -1);
        return nullptr;
    }

    return new IpcStream::DiagnosticsIpc(namedPipeName);
}

IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const
{
    const uint32_t nInBufferSize = 16 * 1024;
    const uint32_t nOutBufferSize = 16 * 1024;
    HANDLE hPipe = ::CreateNamedPipeA(
        _pNamedPipeName,                                            // pipe name
        PIPE_ACCESS_DUPLEX,                                         // read/write access
        PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,    // message type pipe, message-read and blocking mode
        PIPE_UNLIMITED_INSTANCES,                                   // max. instances
        nOutBufferSize,                                             // output buffer size
        nInBufferSize,                                              // input buffer size
        0,                                                          // default client time-out
        NULL);                                                      // default security attribute

    if (hPipe == INVALID_HANDLE_VALUE)
    {
        if (callback != nullptr)
            callback("Failed to create an instance of a named pipe.", ::GetLastError());
        return nullptr;
    }

    const BOOL fSuccess = ::ConnectNamedPipe(hPipe, NULL) != 0;
    if (!fSuccess)
    {
        const DWORD errorCode = ::GetLastError();
        switch (errorCode)
        {
            case ERROR_PIPE_CONNECTED:
                // Occurs when a client connects before the function is called.
                // In this case, there is a connection between client and
                // server, even though the function returned zero.
                break;

            default:
                if (callback != nullptr)
                    callback("A client process failed to connect.", errorCode);
                ::CloseHandle(hPipe);
                return nullptr;
        }
    }

    return new IpcStream(hPipe);
}

void IpcStream::DiagnosticsIpc::Close(ErrorCallback)
{
}

IpcStream::~IpcStream()
{
    if (_hPipe != INVALID_HANDLE_VALUE)
    {
        Flush();

        const BOOL fSuccessDisconnectNamedPipe = ::DisconnectNamedPipe(_hPipe);
        assert(fSuccessDisconnectNamedPipe != 0);

        const BOOL fSuccessCloseHandle = ::CloseHandle(_hPipe);
        assert(fSuccessCloseHandle != 0);
    }
}

bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const
{
    assert(lpBuffer != nullptr);

    DWORD nNumberOfBytesRead = 0;
    const bool fSuccess = ::ReadFile(
        _hPipe,                 // handle to pipe
        lpBuffer,               // buffer to receive data
        nBytesToRead,           // size of buffer
        &nNumberOfBytesRead,    // number of bytes read
        NULL) != 0;             // not overlapped I/O

    if (!fSuccess)
    {
        // TODO: Add error handling.
    }

    nBytesRead = static_cast<uint32_t>(nNumberOfBytesRead);
    return fSuccess;
}

bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const
{
    assert(lpBuffer != nullptr);

    DWORD nNumberOfBytesWritten = 0;
    const bool fSuccess = ::WriteFile(
        _hPipe,                 // handle to pipe
        lpBuffer,               // buffer to write from
        nBytesToWrite,          // number of bytes to write
        &nNumberOfBytesWritten, // number of bytes written
        NULL) != 0;             // not overlapped I/O

    if (!fSuccess)
    {
        // TODO: Add error handling.
    }

    nBytesWritten = static_cast<uint32_t>(nNumberOfBytesWritten);
    return fSuccess;
}

bool IpcStream::Flush() const
{
    const bool fSuccess = ::FlushFileBuffers(_hPipe) != 0;
    if (!fSuccess)
    {
        // TODO: Add error handling.
    }
    return fSuccess;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <array>

void carr_func(int * arr)
{
	std::cout << "carr_func - arr: " << arr << std::endl;
}

int main(void)
{
	//Declares an array of 10 ints. Size is always required
	std::array<int, 10> a1;

	//Declare and initialize
	std::array<int, 5> a2 = {-1, 1, 3, 2, 0};

	std::array<int, 0> a_empty;

	//The std::array container keeps track of size
	std::cout << "a1.size(): " << a1.size() << std::endl;
	std::cout << "a2.size(): " << a2.size() << std::endl;
	//Note: For std::array, size() == max_size()
	std::cout << "a2.max_size(): " << a2.max_size() << std::endl;

	/*
	* Is the array empty?
	* Only if you have an array of size 0. Unitialized arrays still
	* have a size and are never empty!
	*/
	std::cout << "a1.empty(): " << a1.empty() << std::endl;
	std::cout << "a2.empty(): " << a2.empty() << std::endl;
	std::cout << "a_empty.empty(): " << a_empty.empty() << std::endl;

	//Element Access options
	std::cout << "a2.front(): " << a2.front() << std::endl;
	std::cout << "a2.back(): " << a2.back() << std::endl;
	std::cout << "a2[0]: " << a2[0] << std::endl;
	std::cout << "a2.at(4): " << a2.at(4) << std::endl;

	// Bounds checking will generate exceptions. Try:
	//auto b = a2.at(10);

	//However, operator [] is not bounds checked!
	//This may or may not seg fault
	//std::cout << "a2[7]: " << a2[7] << std::endl;

	//Making a new array via copy
	auto a3 = a2;

	//Assigning values works as expected
	a3[0] = -2;

	/*
	* If you need to interface with legacy code or libraries requiring
	* a C-style array interface, you can get to the underlying array data ptr
	*/

	//Error:
	//carr_func(a2);

	//OK:
	carr_func(a2.data());

	// You can use convenient ranged for loops!
	std::cout << std::endl << "a3: " << std::endl;
	for (const auto & t : a3)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	//You can use container operations
	std::sort(a3.begin(), a3.end());

	// You can use convenient ranged for loops!
	std::cout << std::endl << "a3 std::sort: " << std::endl;
	for (const auto & t : a3)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	//Assign a2 to a3's values:
	a2 = a3;

	// But you can only use the '=' operator on arrays of equivalent size.
	//Error:
	//a1 = a2; //<[...],10> vs <[...],5>! invalid

	std::cout << std::endl << "a2, post-assignment: " << std::endl;
	for (const auto & t : a2)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	return 0;
}
<commit_msg>Fix C-style function interface to a better API<commit_after>#include <iostream>
#include <array>

void carr_func(int * arr, size_t size)
{
	std::cout << "carr_func - arr: " << arr << std::endl;
}

int main(void)
{
	//Declares an array of 10 ints. Size is always required
	std::array<int, 10> a1;

	//Declare and initialize
	std::array<int, 5> a2 = {-1, 1, 3, 2, 0};

	std::array<int, 0> a_empty;

	//The std::array container keeps track of size
	std::cout << "a1.size(): " << a1.size() << std::endl;
	std::cout << "a2.size(): " << a2.size() << std::endl;
	//Note: For std::array, size() == max_size()
	std::cout << "a2.max_size(): " << a2.max_size() << std::endl;

	/*
	* Is the array empty?
	* Only if you have an array of size 0. Unitialized arrays still
	* have a size and are never empty!
	*/
	std::cout << "a1.empty(): " << a1.empty() << std::endl;
	std::cout << "a2.empty(): " << a2.empty() << std::endl;
	std::cout << "a_empty.empty(): " << a_empty.empty() << std::endl;

	//Element Access options
	std::cout << "a2.front(): " << a2.front() << std::endl;
	std::cout << "a2.back(): " << a2.back() << std::endl;
	std::cout << "a2[0]: " << a2[0] << std::endl;
	std::cout << "a2.at(4): " << a2.at(4) << std::endl;

	// Bounds checking will generate exceptions. Try:
	//auto b = a2.at(10);

	//However, operator [] is not bounds checked!
	//This may or may not seg fault
	//std::cout << "a2[7]: " << a2[7] << std::endl;

	//Making a new array via copy
	auto a3 = a2;

	//Assigning values works as expected
	a3[0] = -2;

	/*
	* If you need to interface with legacy code or libraries requiring
	* a C-style array interface, you can get to the underlying array data ptr
	*/

	//Error:
	//carr_func(a2, a2.size());

	//OK:
	carr_func(a2.data(), a2.size());

	// You can use convenient ranged for loops!
	std::cout << std::endl << "a3: " << std::endl;
	for (const auto & t : a3)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	//You can use container operations
	std::sort(a3.begin(), a3.end());

	// You can use convenient ranged for loops!
	std::cout << std::endl << "a3 std::sort: " << std::endl;
	for (const auto & t : a3)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	//Assign a2 to a3's values:
	a2 = a3;

	// But you can only use the '=' operator on arrays of equivalent size.
	//Error:
	//a1 = a2; //<[...],10> vs <[...],5>! invalid

	std::cout << std::endl << "a2, post-assignment: " << std::endl;
	for (const auto & t : a2)
	{
		std::cout << t << " ";
	}
	std::cout << std::endl;

	return 0;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//  Range Minimum Query
//  <O(N lg N, lg N or O(1)>
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <vector>
#include <cassert>

using namespace std;

template<class T>
class RangeMinimumQuery {
public:
    vector<vector<int> > M;
    vector<T> A;
    int N;
    RangeMinimumQuery(T in[], int n) {
        N = n;
        M = vector<vector<int> >(N + 5);
        A = vector<T> (N + 5);
        for (int i = 0; i < N + 5; i++)
            M[i] = vector<int> (25);

        //initialize M for the intervals with length 1
        for (int i = 0; i < N; i++) {
            M[i][0] = i;
            A[i] = in[i];
        }
        //compute values from smaller to bigger intervals
        for (int j = 1; 1<<j <= N; j++){
            for (int i = 0; i + (1<<j) - 1 < N; i++)
                if (A[M[i][j - 1]] < A[M[i + (1 << (j - 1))][j - 1]]) M[i][j] = M[i][j - 1];
                else M[i][j] = M[i + (1 << (j - 1))][j - 1];
        }
    }

    // returns min(A[left...right])
    // also can be modified to return the index
    T get_min(int left, int right) {
        int num = right - left + 1;
        int e = 1, k = 0;
        while (e * 2 <= num) e *= 2, k++;
        int temp = right - e + 1;
        if (A[M[left][k]] <= A[M[temp][k]]) return A[M[left][k]];
        else return A[M[temp][k]];
    }
};

int bruteforce_rmq(int *a, int left, int right) {
    int ret = a[left];
    for (int i = left + 1; i <= right; i++) {
        ret = min(ret, a[i]);
    }
    return ret;
}

int main() {
    int N = 15;
    int in[] = {-1, 4, 1, 6, 2, -10, 11, 3, 7, 100, 4, -123123123, 19, 1, -5};
    RangeMinimumQuery<int> rmq(in, N);

    for (int i = 0; i < N; i++) {
        for (int j = i; j < N; j++) {
            assert(rmq.get_min(i, j) == bruteforce_rmq(in, i, j));
        }
    }
    /*
    assert(rmq.get_min(0, 0) == -1);
    assert(rmq.get_min(0, 9) == -10);
    assert(rmq.get_min(0, 2) == -1);
    assert(rmq.get_min(4, 9) == -10);
    assert(rmq.get_min(3, 3) == 6);
    assert(rmq.get_min(6, 8) == 3);
    */
    return 0;
}
<commit_msg>Update RangeMinimumQuery.cpp<commit_after>///////////////////////////////////////////////////////////////////////////////
//  Range Minimum Query
//  <O(N lg N, lg N or O(1)>
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <vector>
#include <cassert>

using namespace std;

template<class T>
class RangeMinimumQuery {
public:
    vector<vector<int> > M;
    vector<T> A;
    int N;
    RangeMinimumQuery(T in[], int n) {
        N = n;
        M = vector<vector<int> >(N + 5);
        A = vector<T> (N + 5);
        int b; for (b = 0; 1<<b <= N; b++);
        for (int i = 0; i < N + 5; i++)
            M[i] = vector<int> (b);

        //initialize M for the intervals with length 1
        for (int i = 0; i < N; i++) {
            M[i][0] = i;
            A[i] = in[i];
        }
        //compute values from smaller to bigger intervals
        for (int j = 1; 1<<j <= N; j++){
            for (int i = 0; i + (1<<j) - 1 < N; i++)
                if (A[M[i][j - 1]] < A[M[i + (1 << (j - 1))][j - 1]]) M[i][j] = M[i][j - 1];
                else M[i][j] = M[i + (1 << (j - 1))][j - 1];
        }
    }

    // returns min(A[left...right])
    // also can be modified to return the index
    T get_min(int left, int right) {
        int num = right - left + 1;
        int e = 1, k = 0;
        while (e * 2 <= num) e *= 2, k++;
        int temp = right - e + 1;
        if (A[M[left][k]] <= A[M[temp][k]]) return A[M[left][k]];
        else return A[M[temp][k]];
    }
};

int bruteforce_rmq(int *a, int left, int right) {
    int ret = a[left];
    for (int i = left + 1; i <= right; i++) {
        ret = min(ret, a[i]);
    }
    return ret;
}

int main() {
    int N = 15;
    int in[] = {-1, 4, 1, 6, 2, -10, 11, 3, 7, 100, 4, -123123123, 19, 1, -5};
    RangeMinimumQuery<int> rmq(in, N);

    for (int i = 0; i < N; i++) {
        for (int j = i; j < N; j++) {
            assert(rmq.get_min(i, j) == bruteforce_rmq(in, i, j));
        }
    }
    /*
    assert(rmq.get_min(0, 0) == -1);
    assert(rmq.get_min(0, 9) == -10);
    assert(rmq.get_min(0, 2) == -1);
    assert(rmq.get_min(4, 9) == -10);
    assert(rmq.get_min(3, 3) == 6);
    assert(rmq.get_min(6, 8) == 3);
    */
    return 0;
}
<|endoftext|>