<commit_before>#include "wordribbonitem.h"

#include "mscalableimage.h"
#include <QString>
#include <QtCore>
#include <QtGui>

namespace {
    static const int FocusZoneMargin = 30;
}

WordRibbonItem::WordRibbonItem(WordRibbon::ItemStyleMode mode, MWidget* parent):
        MStylableWidget(parent),
        label(""),
        mPositionIndex(-1),
        isMousePressCancelled(false),
        highlightEffectEnabled(true),
        forceMaxWidth(-1),
        state(NormalState),
        mode(mode)
{
    if (textPen.color() != style()->fontColor()) {
        textPen.setColor(style()->fontColor());
    }

    recalculateItemSize();
}

WordRibbonItem::~WordRibbonItem()
{
}

void WordRibbonItem::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);

    const WordRibbonItemStyle *s = static_cast<const WordRibbonItemStyle *>(style().operator ->());

    if (!s->backgroundImage() && !s->backgroundImagePressed() && !s->backgroundImageSelected())
        return ;

    qreal oldOpacity = painter->opacity();
    painter->setOpacity(s->backgroundOpacity() * effectiveOpacity());

    QSizeF currentSize = size() - QSizeF(s->marginLeft() + s->marginRight(), s->marginTop() + s->marginBottom());

    switch (state) {
    case NormalState:
        if (s->backgroundImage())
            s->backgroundImage()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    case SelectedState:
        if (s->backgroundImageSelected())
            s->backgroundImageSelected()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    case PressState:
        if (s->backgroundImagePressed())
            s->backgroundImagePressed()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    default:
        break;
    }
    painter->setOpacity(oldOpacity);
}

void WordRibbonItem::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    if (label.length() == 0) {
        //No content inside candidate item.
        MStylableWidget::drawContents(painter, option);
        return ;
    }

    painter->setFont(drawFont);
    painter->setPen(textPen);

    if (mode == WordRibbon::RibbonStyleMode)
        painter->drawText(contentRect, Qt::AlignCenter, label);
    else
        painter->drawText(contentRect, Qt::AlignLeft, label);
}

QSizeF WordRibbonItem::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
{
    Q_UNUSED(constraint);

    QSizeF size ;

    switch (which) {
    case Qt::MinimumSize:
        size = minimumSize;
        break;
    case Qt::PreferredSize:
        size = preferredSize;
        break;
    case Qt::MaximumSize:
        if (forceMaxWidth > 0) {
            size = preferredSize;
            size.setWidth(forceMaxWidth);
        }
        else {
            size = style()->maximumSize();
        }
        break;
    default:
        break;
    }
    return size;
}

void WordRibbonItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    if (!paddingRect.contains(event->pos().toPoint())) {
        isMousePressCancelled = true;
        return ;
    }

    isMousePressCancelled = false;
    updateStyleState(PressState);

    emit mousePressed();
}

void WordRibbonItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    Q_UNUSED(event);
    if (isMousePressCancelled)
        return ;
    else {
        highlight();
        emit mouseReleased();
    }
}

void WordRibbonItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
    if (isMousePressCancelled)
        return ;

    if (mode == WordRibbon::DialogStyleMode) {
        if (!paddingRect.contains(event->pos().toPoint())) {
            // In "DialogStyleMode", when the touch point has been moved
            // out of the area of current item, its "Pressed" state should
            // be cancelled.
            isMousePressCancelled = true;
            clearPress();
        }
    } else {
        QRect moveRect = paddingRect.adjusted(-FocusZoneMargin,
                                              -FocusZoneMargin,
                                              +FocusZoneMargin,
                                              +FocusZoneMargin);
        if (!moveRect.contains(event->pos().toPoint())) {
            // In "RibbonStyleMode", even if the touch point is moved out of
            // the valid touch area of current item, its "Highlighted" state
            // should be kept.
            isMousePressCancelled = true;
            highlight();
        }
    }
}

void WordRibbonItem::cancelEvent(MCancelEvent *event)
{
    Q_UNUSED(event);
    isMousePressCancelled = true;
    clearPress();
}

void WordRibbonItem::setText(const QString& str)
{
    label = str;
    applyStyle();
    recalculateItemSize();
    update();
    updateGeometry();
}

void WordRibbonItem::clearText()
{
    setText ("");
}

QString WordRibbonItem::text()
{
    return label;
}

void WordRibbonItem::enableHighlight()
{
    highlightEffectEnabled = true;
}

void WordRibbonItem::disableHighlight()
{
    highlightEffectEnabled = false;
}

void WordRibbonItem::highlight()
{
    if (!highlightEffectEnabled
        || highlighted()) {
        return ;
    }

    updateStyleState(SelectedState);
}

void WordRibbonItem::press()
{
    if (!pressed())
        updateStyleState(PressState);
}

void WordRibbonItem::clearHighlight()
{
    if (highlighted())
        updateStyleState(NormalState);
}

void WordRibbonItem::clearPress()
{
    if (pressed())
        updateStyleState(NormalState);
}

bool WordRibbonItem::highlighted() const
{
    if (!highlightEffectEnabled) {
        return false;
    }
    return state == SelectedState;
}

bool WordRibbonItem::pressed() const
{
    return state == PressState;
}

void WordRibbonItem::setPositionIndex(int index)
{
    mPositionIndex = index;
}

int WordRibbonItem::positionIndex() const
{
    return mPositionIndex;
}

void WordRibbonItem::applyStyle()
{
    if (mode == WordRibbon::DialogStyleMode) {
        // In WordRibbon::DialogStyleMode the margins and paddings are depending
        // on the length of the label
        switch (label.length()) {
        case 1:
            style().setModeDialogstyleoneword();
            break;
        case 2:
            style().setModeDialogstyletwoword();
            break;
        case 3:
            style().setModeDialogstylethreeword();
            break;
        default:
            style().setModeDialogstyleseveralword();
            break;
        }
    } else {
        // In WordRibbon::RibbonStyleMode the margins and paddings are depending
        // on the length of the label
        switch (label.length()) {
        case 0:
            style().setModeDefault();
            break;
        case 1:
            style().setModeRibbonstyleoneword();
            break;
        default:
            style().setModeRibbonstyleseveralword();
            break;
        }
    }
}

void WordRibbonItem::recalculateItemSize()
{
    int paddingLeft, paddingRight, paddingTop, paddingBottom;
    int marginLeft, marginRight, marginTop, marginBottom;

    paddingLeft = style()->paddingLeft();
    paddingRight = style()->paddingRight();
    paddingTop = style()->paddingTop();
    paddingBottom = style()->paddingBottom();
    marginLeft = style()->marginLeft();
    marginRight = style()->marginRight();
    marginTop = style()->marginTop();
    marginBottom = style()->marginBottom();

    minimumSize = style()->minimumSize();
    drawFont = style()->font();

    if (label.length() == 0) {
        preferredSize = minimumSize;
    } else {
        // If label has characters, then the size of this widget
        // need to be update by calculating padding and margin.
        QFontMetrics fm(drawFont);
        QSize textSize = fm.size(Qt::TextSingleLine, label);

        if (mode == WordRibbon::DialogStyleMode) {
            // In WordRibbon::DialogStyleMode, reduce font size for long label
            // to fit the item width
            int maxWidth = forceMaxWidth > 0 ?
                           forceMaxWidth :
                           style()->maximumSize().width();

            int currentWidth = textSize.width() +
                             marginLeft + marginRight +
                             paddingLeft + paddingRight;

            while (currentWidth > maxWidth) {
                if (drawFont.pixelSize() <= 5) {
                    // too small
                    break;
                }
                drawFont.setPixelSize(drawFont.pixelSize() - 1);
                textSize = fm.size(Qt::TextSingleLine, label);

                currentWidth = textSize.width() +
                               marginLeft + marginRight +
                               paddingLeft + paddingRight;
            }
        }

        preferredSize.setWidth(textSize.width() +
                               marginLeft + marginRight +
                               paddingLeft + paddingRight);

        preferredSize.setHeight(textSize.height() +
                                marginTop + marginBottom +
                                paddingTop + paddingBottom);

        minimumSize = preferredSize;
    }

    setMinimumSize(minimumSize);
    setPreferredSize(preferredSize);

    QSizeF tmpSize = preferredSize - QSizeF(marginLeft + marginRight,
                                            marginTop + marginBottom);

    paddingRect = QRect(marginLeft, marginTop,
                        tmpSize.width(), tmpSize.height());

    tmpSize = tmpSize - QSizeF(paddingLeft + paddingRight,
                               paddingTop + paddingBottom);

    // ContentRect represents the drawing text area used in drawContents() function.
    // Don't need to calculate margin area.
    // Becuase in MWidgetView::paint(), it will call:
    // painter->translate(horizontalMargin, d->margins.top());
    contentRect = QRect(paddingLeft,
                        paddingTop,
                        tmpSize.width(),
                        tmpSize.height());

    resize(preferredSize);
}

void WordRibbonItem::updateStyleState(ItemState newState)
{
    state = newState;
    switch (state) {
    case NormalState:
        textPen.setColor(style()->fontColor());
        break;
    case SelectedState:
        textPen.setColor(style()->selectedFontColor());
        break;
    case PressState:
        textPen.setColor(style()->pressedFontColor());
        break;
    default:
        break;
    }

    update();
}

void WordRibbonItem::setMaxWidth(int width)
{
    if (width < style()->minimumSize().width())
        return;

    forceMaxWidth = width;
}
<commit_msg>Changes: Fix a bug that incorrect highlighted state displays in WordRibbonDialog.<commit_after>#include "wordribbonitem.h"

#include "mscalableimage.h"
#include <QString>
#include <QtCore>
#include <QtGui>

namespace {
    static const int FocusZoneMargin = 30;
}

WordRibbonItem::WordRibbonItem(WordRibbon::ItemStyleMode mode, MWidget* parent):
        MStylableWidget(parent),
        label(""),
        mPositionIndex(-1),
        isMousePressCancelled(false),
        highlightEffectEnabled(true),
        forceMaxWidth(-1),
        state(NormalState),
        mode(mode)
{
    if (textPen.color() != style()->fontColor()) {
        textPen.setColor(style()->fontColor());
    }

    recalculateItemSize();
}

WordRibbonItem::~WordRibbonItem()
{
}

void WordRibbonItem::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);

    const WordRibbonItemStyle *s = static_cast<const WordRibbonItemStyle *>(style().operator ->());

    if (!s->backgroundImage() && !s->backgroundImagePressed() && !s->backgroundImageSelected())
        return ;

    qreal oldOpacity = painter->opacity();
    painter->setOpacity(s->backgroundOpacity() * effectiveOpacity());

    QSizeF currentSize = size() - QSizeF(s->marginLeft() + s->marginRight(), s->marginTop() + s->marginBottom());

    switch (state) {
    case NormalState:
        if (s->backgroundImage())
            s->backgroundImage()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    case SelectedState:
        if (s->backgroundImageSelected())
            s->backgroundImageSelected()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    case PressState:
        if (s->backgroundImagePressed())
            s->backgroundImagePressed()->draw(0.0, 0.0, currentSize.width(), currentSize.height(), painter);
        break;
    default:
        break;
    }
    painter->setOpacity(oldOpacity);
}

void WordRibbonItem::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    if (label.length() == 0) {
        //No content inside candidate item.
        MStylableWidget::drawContents(painter, option);
        return ;
    }

    painter->setFont(drawFont);
    painter->setPen(textPen);

    if (mode == WordRibbon::RibbonStyleMode)
        painter->drawText(contentRect, Qt::AlignCenter, label);
    else
        painter->drawText(contentRect, Qt::AlignLeft, label);
}

QSizeF WordRibbonItem::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
{
    Q_UNUSED(constraint);

    QSizeF size ;

    switch (which) {
    case Qt::MinimumSize:
        size = minimumSize;
        break;
    case Qt::PreferredSize:
        size = preferredSize;
        break;
    case Qt::MaximumSize:
        if (forceMaxWidth > 0) {
            size = preferredSize;
            size.setWidth(forceMaxWidth);
        }
        else {
            size = style()->maximumSize();
        }
        break;
    default:
        break;
    }
    return size;
}

void WordRibbonItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    if (!paddingRect.contains(event->pos().toPoint())) {
        isMousePressCancelled = true;
        return ;
    }

    isMousePressCancelled = false;
    updateStyleState(PressState);

    emit mousePressed();
}

void WordRibbonItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    Q_UNUSED(event);
    if (isMousePressCancelled)
        return ;
    else {
        // Only show "highlighted" state for RibbonStyleMode here.
        if (mode == WordRibbon::RibbonStyleMode)
            highlight();

        emit mouseReleased();
    }
}

void WordRibbonItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
    if (isMousePressCancelled)
        return ;

    if (mode == WordRibbon::DialogStyleMode) {
        if (!paddingRect.contains(event->pos().toPoint())) {
            // In "DialogStyleMode", when the touch point has been moved
            // out of the area of current item, its "Pressed" state should
            // be cancelled.
            isMousePressCancelled = true;
            clearPress();
        }
    } else {
        QRect moveRect = paddingRect.adjusted(-FocusZoneMargin,
                                              -FocusZoneMargin,
                                              +FocusZoneMargin,
                                              +FocusZoneMargin);
        if (!moveRect.contains(event->pos().toPoint())) {
            // In "RibbonStyleMode", even if the touch point is moved out of
            // the valid touch area of current item, its "Highlighted" state
            // should be kept.
            isMousePressCancelled = true;
            highlight();
        }
    }
}

void WordRibbonItem::cancelEvent(MCancelEvent *event)
{
    Q_UNUSED(event);
    isMousePressCancelled = true;
    clearPress();
}

void WordRibbonItem::setText(const QString& str)
{
    label = str;
    applyStyle();
    recalculateItemSize();
    update();
    updateGeometry();
}

void WordRibbonItem::clearText()
{
    setText ("");
}

QString WordRibbonItem::text()
{
    return label;
}

void WordRibbonItem::enableHighlight()
{
    highlightEffectEnabled = true;
}

void WordRibbonItem::disableHighlight()
{
    highlightEffectEnabled = false;
}

void WordRibbonItem::highlight()
{
    if (!highlightEffectEnabled
        || highlighted()) {
        return ;
    }

    updateStyleState(SelectedState);
}

void WordRibbonItem::press()
{
    if (!pressed())
        updateStyleState(PressState);
}

void WordRibbonItem::clearHighlight()
{
    if (highlighted())
        updateStyleState(NormalState);
}

void WordRibbonItem::clearPress()
{
    if (pressed())
        updateStyleState(NormalState);
}

bool WordRibbonItem::highlighted() const
{
    if (!highlightEffectEnabled) {
        return false;
    }
    return state == SelectedState;
}

bool WordRibbonItem::pressed() const
{
    return state == PressState;
}

void WordRibbonItem::setPositionIndex(int index)
{
    mPositionIndex = index;
}

int WordRibbonItem::positionIndex() const
{
    return mPositionIndex;
}

void WordRibbonItem::applyStyle()
{
    if (mode == WordRibbon::DialogStyleMode) {
        // In WordRibbon::DialogStyleMode the margins and paddings are depending
        // on the length of the label
        switch (label.length()) {
        case 1:
            style().setModeDialogstyleoneword();
            break;
        case 2:
            style().setModeDialogstyletwoword();
            break;
        case 3:
            style().setModeDialogstylethreeword();
            break;
        default:
            style().setModeDialogstyleseveralword();
            break;
        }
    } else {
        // In WordRibbon::RibbonStyleMode the margins and paddings are depending
        // on the length of the label
        switch (label.length()) {
        case 0:
            style().setModeDefault();
            break;
        case 1:
            style().setModeRibbonstyleoneword();
            break;
        default:
            style().setModeRibbonstyleseveralword();
            break;
        }
    }
}

void WordRibbonItem::recalculateItemSize()
{
    int paddingLeft, paddingRight, paddingTop, paddingBottom;
    int marginLeft, marginRight, marginTop, marginBottom;

    paddingLeft = style()->paddingLeft();
    paddingRight = style()->paddingRight();
    paddingTop = style()->paddingTop();
    paddingBottom = style()->paddingBottom();
    marginLeft = style()->marginLeft();
    marginRight = style()->marginRight();
    marginTop = style()->marginTop();
    marginBottom = style()->marginBottom();

    minimumSize = style()->minimumSize();
    drawFont = style()->font();

    if (label.length() == 0) {
        preferredSize = minimumSize;
    } else {
        // If label has characters, then the size of this widget
        // need to be update by calculating padding and margin.
        QFontMetrics fm(drawFont);
        QSize textSize = fm.size(Qt::TextSingleLine, label);

        if (mode == WordRibbon::DialogStyleMode) {
            // In WordRibbon::DialogStyleMode, reduce font size for long label
            // to fit the item width
            int maxWidth = forceMaxWidth > 0 ?
                           forceMaxWidth :
                           style()->maximumSize().width();

            int currentWidth = textSize.width() +
                             marginLeft + marginRight +
                             paddingLeft + paddingRight;

            while (currentWidth > maxWidth) {
                if (drawFont.pixelSize() <= 5) {
                    // too small
                    break;
                }
                drawFont.setPixelSize(drawFont.pixelSize() - 1);
                textSize = fm.size(Qt::TextSingleLine, label);

                currentWidth = textSize.width() +
                               marginLeft + marginRight +
                               paddingLeft + paddingRight;
            }
        }

        preferredSize.setWidth(textSize.width() +
                               marginLeft + marginRight +
                               paddingLeft + paddingRight);

        preferredSize.setHeight(textSize.height() +
                                marginTop + marginBottom +
                                paddingTop + paddingBottom);

        minimumSize = preferredSize;
    }

    setMinimumSize(minimumSize);
    setPreferredSize(preferredSize);

    QSizeF tmpSize = preferredSize - QSizeF(marginLeft + marginRight,
                                            marginTop + marginBottom);

    paddingRect = QRect(marginLeft, marginTop,
                        tmpSize.width(), tmpSize.height());

    tmpSize = tmpSize - QSizeF(paddingLeft + paddingRight,
                               paddingTop + paddingBottom);

    // ContentRect represents the drawing text area used in drawContents() function.
    // Don't need to calculate margin area.
    // Becuase in MWidgetView::paint(), it will call:
    // painter->translate(horizontalMargin, d->margins.top());
    contentRect = QRect(paddingLeft,
                        paddingTop,
                        tmpSize.width(),
                        tmpSize.height());

    resize(preferredSize);
}

void WordRibbonItem::updateStyleState(ItemState newState)
{
    state = newState;
    switch (state) {
    case NormalState:
        textPen.setColor(style()->fontColor());
        break;
    case SelectedState:
        textPen.setColor(style()->selectedFontColor());
        break;
    case PressState:
        textPen.setColor(style()->pressedFontColor());
        break;
    default:
        break;
    }

    update();
}

void WordRibbonItem::setMaxWidth(int width)
{
    if (width < style()->minimumSize().width())
        return;

    forceMaxWidth = width;
}
<|endoftext|>


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

#include "xwalk/application/browser/application_protocols.h"

#include <algorithm>
#include <map>
#include <list>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_math.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "url/url_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_simple_job.h"
#include "xwalk/application/browser/application_service.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_file_util.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/application_resource.h"
#include "xwalk/application/common/constants.h"
#include "xwalk/application/common/manifest_handlers/csp_handler.h"
#include "xwalk/runtime/common/xwalk_system_locale.h"

using content::BrowserThread;
using content::ResourceRequestInfo;

namespace xwalk {

namespace keys = application_manifest_keys;

namespace application {

namespace {

net::HttpResponseHeaders* BuildHttpHeaders(
    const std::string& content_security_policy,
    const std::string& mime_type, const std::string& method,
    const base::FilePath& file_path, const base::FilePath& relative_path,
    bool is_authority_match) {
  std::string raw_headers;
  if (method == "GET") {
    if (relative_path.empty())
      raw_headers.append("HTTP/1.1 400 Bad Request");
    else if (!is_authority_match)
      raw_headers.append("HTTP/1.1 403 Forbidden");
    else if (file_path.empty())
      raw_headers.append("HTTP/1.1 404 Not Found");
    else
      raw_headers.append("HTTP/1.1 200 OK");
  } else {
    raw_headers.append("HTTP/1.1 501 Not Implemented");
  }

  if (!content_security_policy.empty()) {
    raw_headers.append(1, '\0');
    raw_headers.append("Content-Security-Policy: ");
    raw_headers.append(content_security_policy);
  }

  raw_headers.append(1, '\0');
  raw_headers.append("Access-Control-Allow-Origin: *");

  if (!mime_type.empty()) {
    raw_headers.append(1, '\0');
    raw_headers.append("Content-Type: ");
    raw_headers.append(mime_type);
  }

  raw_headers.append(2, '\0');
  return new net::HttpResponseHeaders(raw_headers);
}

void ReadResourceFilePath(
    const ApplicationResource& resource,
    base::FilePath* file_path) {
  *file_path = resource.GetFilePath();
}

class URLRequestApplicationJob : public net::URLRequestFileJob {
 public:
  URLRequestApplicationJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate,
      const scoped_refptr<base::TaskRunner>& file_task_runner,
      const std::string& application_id,
      const base::FilePath& directory_path,
      const base::FilePath& relative_path,
      const std::string& content_security_policy,
      const std::list<std::string>& locales,
      bool is_authority_match)
      : net::URLRequestFileJob(
          request, network_delegate, base::FilePath(), file_task_runner),
        content_security_policy_(content_security_policy),
        locales_(locales),
        resource_(application_id, directory_path, relative_path),
        relative_path_(relative_path),
        is_authority_match_(is_authority_match),
        weak_factory_(this) {
  }

  void GetResponseInfo(net::HttpResponseInfo* info) override {
    std::string mime_type;
    GetMimeType(&mime_type);
    std::string method = request()->method();
    response_info_.headers = BuildHttpHeaders(
        content_security_policy_, mime_type, method, file_path_,
        relative_path_, is_authority_match_);
    *info = response_info_;
  }

  void Start() override {
    base::FilePath* read_file_path = new base::FilePath;

    resource_.SetLocales(locales_);
    bool posted = base::WorkerPool::PostTaskAndReply(
        FROM_HERE,
        base::Bind(&ReadResourceFilePath, resource_,
                   base::Unretained(read_file_path)),
        base::Bind(&URLRequestApplicationJob::OnFilePathRead,
                   weak_factory_.GetWeakPtr(),
                   base::Owned(read_file_path)),
        true /* task is slow */);
    DCHECK(posted);
  }

 protected:
  ~URLRequestApplicationJob() override {}

  std::string content_security_policy_;
  std::list<std::string> locales_;
  ApplicationResource resource_;
  base::FilePath relative_path_;

 private:
  void OnFilePathRead(base::FilePath* read_file_path) {
    file_path_ = *read_file_path;
    if (file_path_.empty())
      NotifyHeadersComplete();
    else
      URLRequestFileJob::Start();
  }

  net::HttpResponseInfo response_info_;
  bool is_authority_match_;
  base::WeakPtrFactory<URLRequestApplicationJob> weak_factory_;
};

// This class is a thread-safe cache of active application's data.
// This class is used by ApplicationProtocolHandler which lives on
// IO thread and hence cannot access ApplicationService directly.
class ApplicationDataCache : public ApplicationService::Observer {
 public:
  scoped_refptr<ApplicationData> GetApplicationData(
      const std::string& application_id) const {
    base::AutoLock lock(lock_);
    ApplicationData::ApplicationDataMap::const_iterator it =
        cache_.find(application_id);
    if (it != cache_.end()) {
      return it->second;
    }
    return NULL;
  }

  static void CreateIfNeeded(ApplicationService* service) {
    DCHECK(service);
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    if (s_instance_)
      return;
    // The cache lives longer than ApplicationService,
    // so we do not need to remove cache_ from ApplicationService
    // observers list.
    s_instance_ = new ApplicationDataCache();
    service->AddObserver(s_instance_);
  }

  static ApplicationDataCache* Get() { return s_instance_;}

 private:
  void DidLaunchApplication(Application* app) override {
    base::AutoLock lock(lock_);
    cache_.insert(std::pair<std::string, scoped_refptr<ApplicationData> >(
        app->id(), app->data()));
  }

  void WillDestroyApplication(Application* app) override {
    base::AutoLock lock(lock_);
    cache_.erase(app->id());
  }

  ApplicationDataCache() = default;
  // The life time of the cache instance is equal to the process life time,
  // it is not supposed to be explicitly destroyed.
  ~ApplicationDataCache() override = default;

  ApplicationData::ApplicationDataMap cache_;
  mutable base::Lock lock_;

  static ApplicationDataCache* s_instance_;
};

ApplicationDataCache* ApplicationDataCache::s_instance_;

class ApplicationProtocolHandler
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  explicit ApplicationProtocolHandler(ApplicationService* service) {
    ApplicationDataCache::CreateIfNeeded(service);
  }

  ~ApplicationProtocolHandler() override {}

  net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override;

 private:
  DISALLOW_COPY_AND_ASSIGN(ApplicationProtocolHandler);
};

// The |locale| should be expanded to user agent locale.
// Such as, "en-us" will be expaned as "en-us, en".
void GetUserAgentLocales(const std::string& sys_locale,
                         std::list<std::string>& ua_locales) {  // NOLINT
  if (sys_locale.empty())
    return;

  std::string locale = base::ToLowerASCII(sys_locale);
  size_t position;
  do {
    ua_locales.push_back(locale);
    position = locale.find_last_of("-");
    locale = locale.substr(0, position);
  } while (position != std::string::npos);
}

net::URLRequestJob*
ApplicationProtocolHandler::MaybeCreateJob(
    net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
  const std::string& application_id = request->url().host();
  scoped_refptr<ApplicationData> application =
      ApplicationDataCache::Get()->GetApplicationData(application_id);

  if (!application.get())
    return new net::URLRequestErrorJob(
        request, network_delegate, net::ERR_FILE_NOT_FOUND);

  base::FilePath relative_path =
      ApplicationURLToRelativeFilePath(request->url());
  base::FilePath directory_path;
  std::string content_security_policy;
  if (application.get()) {
    directory_path = application->path();

    const char* csp_key = GetCSPKey(application->manifest_type());
    const CSPInfo* csp_info = static_cast<CSPInfo*>(
          application->GetManifestData(csp_key));
    if (csp_info) {
      const std::map<std::string, std::vector<std::string> >& policies =
          csp_info->GetDirectives();
      std::map<std::string, std::vector<std::string> >::const_iterator it =
          policies.begin();
      for (; it != policies.end(); ++it) {
        content_security_policy.append(
              it->first + ' ' + base::JoinString(it->second, ",") + ';');
      }
    }
  }

  std::list<std::string> locales;
  if (application.get() &&
      application->manifest_type() == Manifest::TYPE_WIDGET) {
    GetUserAgentLocales(GetSystemLocale(), locales);
    GetUserAgentLocales(application->GetManifest()->default_locale(), locales);
  }

  return new URLRequestApplicationJob(
      request,
      network_delegate,
      content::BrowserThread::GetBlockingPool()->
      GetTaskRunnerWithShutdownBehavior(
          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
      application_id,
      directory_path,
      relative_path,
      content_security_policy,
      locales,
      application.get());
}

}  // namespace

linked_ptr<net::URLRequestJobFactory::ProtocolHandler>
CreateApplicationProtocolHandler(ApplicationService* service) {
  return linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
      new ApplicationProtocolHandler(service));
}

}  // namespace application
}  // namespace xwalk
<commit_msg>[Windows][Linux]Fix CSP HTTP request syntax<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/browser/application_protocols.h"

#include <algorithm>
#include <map>
#include <list>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_math.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "url/url_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_simple_job.h"
#include "xwalk/application/browser/application_service.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_file_util.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/application_resource.h"
#include "xwalk/application/common/constants.h"
#include "xwalk/application/common/manifest_handlers/csp_handler.h"
#include "xwalk/runtime/common/xwalk_system_locale.h"

using content::BrowserThread;
using content::ResourceRequestInfo;

namespace xwalk {

namespace keys = application_manifest_keys;

namespace application {

namespace {

net::HttpResponseHeaders* BuildHttpHeaders(
    const std::string& content_security_policy,
    const std::string& mime_type, const std::string& method,
    const base::FilePath& file_path, const base::FilePath& relative_path,
    bool is_authority_match) {
  std::string raw_headers;
  if (method == "GET") {
    if (relative_path.empty())
      raw_headers.append("HTTP/1.1 400 Bad Request");
    else if (!is_authority_match)
      raw_headers.append("HTTP/1.1 403 Forbidden");
    else if (file_path.empty())
      raw_headers.append("HTTP/1.1 404 Not Found");
    else
      raw_headers.append("HTTP/1.1 200 OK");
  } else {
    raw_headers.append("HTTP/1.1 501 Not Implemented");
  }

  if (!content_security_policy.empty()) {
    raw_headers.append(1, '\0');
    raw_headers.append("Content-Security-Policy: ");
    raw_headers.append(content_security_policy);
  }

  raw_headers.append(1, '\0');
  raw_headers.append("Access-Control-Allow-Origin: *");

  if (!mime_type.empty()) {
    raw_headers.append(1, '\0');
    raw_headers.append("Content-Type: ");
    raw_headers.append(mime_type);
  }

  raw_headers.append(2, '\0');
  return new net::HttpResponseHeaders(raw_headers);
}

void ReadResourceFilePath(
    const ApplicationResource& resource,
    base::FilePath* file_path) {
  *file_path = resource.GetFilePath();
}

class URLRequestApplicationJob : public net::URLRequestFileJob {
 public:
  URLRequestApplicationJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate,
      const scoped_refptr<base::TaskRunner>& file_task_runner,
      const std::string& application_id,
      const base::FilePath& directory_path,
      const base::FilePath& relative_path,
      const std::string& content_security_policy,
      const std::list<std::string>& locales,
      bool is_authority_match)
      : net::URLRequestFileJob(
          request, network_delegate, base::FilePath(), file_task_runner),
        content_security_policy_(content_security_policy),
        locales_(locales),
        resource_(application_id, directory_path, relative_path),
        relative_path_(relative_path),
        is_authority_match_(is_authority_match),
        weak_factory_(this) {
  }

  void GetResponseInfo(net::HttpResponseInfo* info) override {
    std::string mime_type;
    GetMimeType(&mime_type);
    std::string method = request()->method();
    response_info_.headers = BuildHttpHeaders(
        content_security_policy_, mime_type, method, file_path_,
        relative_path_, is_authority_match_);
    *info = response_info_;
  }

  void Start() override {
    base::FilePath* read_file_path = new base::FilePath;

    resource_.SetLocales(locales_);
    bool posted = base::WorkerPool::PostTaskAndReply(
        FROM_HERE,
        base::Bind(&ReadResourceFilePath, resource_,
                   base::Unretained(read_file_path)),
        base::Bind(&URLRequestApplicationJob::OnFilePathRead,
                   weak_factory_.GetWeakPtr(),
                   base::Owned(read_file_path)),
        true /* task is slow */);
    DCHECK(posted);
  }

 protected:
  ~URLRequestApplicationJob() override {}

  std::string content_security_policy_;
  std::list<std::string> locales_;
  ApplicationResource resource_;
  base::FilePath relative_path_;

 private:
  void OnFilePathRead(base::FilePath* read_file_path) {
    file_path_ = *read_file_path;
    if (file_path_.empty())
      NotifyHeadersComplete();
    else
      URLRequestFileJob::Start();
  }

  net::HttpResponseInfo response_info_;
  bool is_authority_match_;
  base::WeakPtrFactory<URLRequestApplicationJob> weak_factory_;
};

// This class is a thread-safe cache of active application's data.
// This class is used by ApplicationProtocolHandler which lives on
// IO thread and hence cannot access ApplicationService directly.
class ApplicationDataCache : public ApplicationService::Observer {
 public:
  scoped_refptr<ApplicationData> GetApplicationData(
      const std::string& application_id) const {
    base::AutoLock lock(lock_);
    ApplicationData::ApplicationDataMap::const_iterator it =
        cache_.find(application_id);
    if (it != cache_.end()) {
      return it->second;
    }
    return NULL;
  }

  static void CreateIfNeeded(ApplicationService* service) {
    DCHECK(service);
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    if (s_instance_)
      return;
    // The cache lives longer than ApplicationService,
    // so we do not need to remove cache_ from ApplicationService
    // observers list.
    s_instance_ = new ApplicationDataCache();
    service->AddObserver(s_instance_);
  }

  static ApplicationDataCache* Get() { return s_instance_;}

 private:
  void DidLaunchApplication(Application* app) override {
    base::AutoLock lock(lock_);
    cache_.insert(std::pair<std::string, scoped_refptr<ApplicationData> >(
        app->id(), app->data()));
  }

  void WillDestroyApplication(Application* app) override {
    base::AutoLock lock(lock_);
    cache_.erase(app->id());
  }

  ApplicationDataCache() = default;
  // The life time of the cache instance is equal to the process life time,
  // it is not supposed to be explicitly destroyed.
  ~ApplicationDataCache() override = default;

  ApplicationData::ApplicationDataMap cache_;
  mutable base::Lock lock_;

  static ApplicationDataCache* s_instance_;
};

ApplicationDataCache* ApplicationDataCache::s_instance_;

class ApplicationProtocolHandler
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  explicit ApplicationProtocolHandler(ApplicationService* service) {
    ApplicationDataCache::CreateIfNeeded(service);
  }

  ~ApplicationProtocolHandler() override {}

  net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override;

 private:
  DISALLOW_COPY_AND_ASSIGN(ApplicationProtocolHandler);
};

// The |locale| should be expanded to user agent locale.
// Such as, "en-us" will be expaned as "en-us, en".
void GetUserAgentLocales(const std::string& sys_locale,
                         std::list<std::string>& ua_locales) {  // NOLINT
  if (sys_locale.empty())
    return;

  std::string locale = base::ToLowerASCII(sys_locale);
  size_t position;
  do {
    ua_locales.push_back(locale);
    position = locale.find_last_of("-");
    locale = locale.substr(0, position);
  } while (position != std::string::npos);
}

namespace {
const char kSpace[] = " ";
const char kSemicolon[] = ";";
}  // namespace

net::URLRequestJob*
ApplicationProtocolHandler::MaybeCreateJob(
    net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
  const std::string& application_id = request->url().host();
  scoped_refptr<ApplicationData> application =
      ApplicationDataCache::Get()->GetApplicationData(application_id);

  if (!application.get())
    return new net::URLRequestErrorJob(
        request, network_delegate, net::ERR_FILE_NOT_FOUND);

  base::FilePath relative_path =
      ApplicationURLToRelativeFilePath(request->url());
  base::FilePath directory_path;
  std::string content_security_policy;
  if (application.get()) {
    directory_path = application->path();
    const char* csp_key = GetCSPKey(application->manifest_type());
    const CSPInfo* csp_info = static_cast<CSPInfo*>(
          application->GetManifestData(csp_key));
    if (csp_info) {
      for (auto& directive : csp_info->GetDirectives()) {
        content_security_policy.append(directive.first)
                               .append(kSpace)
                               .append(base::JoinString(directive.second,
                                                        kSpace))
                               .append(kSemicolon);
      }
    }
  }

  std::list<std::string> locales;
  if (application.get() &&
      application->manifest_type() == Manifest::TYPE_WIDGET) {
    GetUserAgentLocales(GetSystemLocale(), locales);
    GetUserAgentLocales(application->GetManifest()->default_locale(), locales);
  }

  return new URLRequestApplicationJob(
      request,
      network_delegate,
      content::BrowserThread::GetBlockingPool()->
      GetTaskRunnerWithShutdownBehavior(
          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
      application_id,
      directory_path,
      relative_path,
      content_security_policy,
      locales,
      application.get());
}

}  // namespace

linked_ptr<net::URLRequestJobFactory::ProtocolHandler>
CreateApplicationProtocolHandler(ApplicationService* service) {
  return linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
      new ApplicationProtocolHandler(service));
}

}  // namespace application
}  // namespace xwalk
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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 "common/common.h"
#include "nordic_common.h"

#include "btle.h"
#include "btle_clock.h"

#include "ble_flash.h"
#include "ble_conn_params.h"

#include "btle_gap.h"
#include "custom/custom_helper.h"

#include "ble/GapEvents.h"
#include "nRF5xn.h"

#ifdef S110
    #define IS_LEGACY_DEVICE_MANAGER_ENABLED 1
#elif defined(S130) || defined(S132)
    #define IS_LEGACY_DEVICE_MANAGER_ENABLED 0
#endif

extern "C" {
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
    #include "pstorage.h"
#else
    #include "fstorage.h"
    #include "fds.h"
    #include "ble_conn_state.h"
#endif

#include "softdevice_handler.h"
#include "ble_stack_handler_types.h"
}

#include "nrf_ble_hci.h"

#include "nRF5XPalGattClient.h"
#include "nRF5XPalSecurityManager.h"

bool isEventsSignaled = false;

extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
void            app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector.

static void btle_handler(ble_evt_t *p_ble_evt);

static void sys_evt_dispatch(uint32_t sys_evt)
{
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
    pstorage_sys_event_handler(sys_evt);
#else
    // Forward Softdevice events to the fstorage module
    fs_sys_event_handler(sys_evt);
#endif
}

/**
 * This function is called in interrupt context to handle BLE events; i.e. pull
 * system and user events out of the pending events-queue of the BLE stack. The
 * BLE stack signals the availability of events by the triggering the SWI2
 * interrupt, which forwards the handling to this function.
 *
 * The event processing loop is implemented in intern_softdevice_events_execute().
 *
 * This function will signal to the user code by calling signalEventsToProcess
 * that their is events to process and BLE::processEvents should be called.
 */
static uint32_t signalEvent()
{
    if(isEventsSignaled == false) {
        isEventsSignaled = true;
        nRF5xn::Instance(BLE::DEFAULT_INSTANCE).signalEventsToProcess(BLE::DEFAULT_INSTANCE);
    }
    return NRF_SUCCESS;
}

error_t btle_init(void)
{
    nrf_clock_lf_cfg_t clockConfiguration;

    // register softdevice handler vector
    NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);

    // Configure the LF clock according to values provided by btle_clock.h.
    // It is input from the chain of the yotta configuration system.
    clockConfiguration.source        = LFCLK_CONF_SOURCE;
    clockConfiguration.xtal_accuracy = LFCLK_CONF_ACCURACY;
    clockConfiguration.rc_ctiv       = LFCLK_CONF_RC_CTIV;
    clockConfiguration.rc_temp_ctiv  = LFCLK_CONF_RC_TEMP_CTIV;

    SOFTDEVICE_HANDLER_INIT(&clockConfiguration, signalEvent);

    // Enable BLE stack
    /**
     * Using this call, the application can select whether to include the
     * Service Changed characteristic in the GATT Server. The default in all
     * previous releases has been to include the Service Changed characteristic,
     * but this affects how GATT clients behave. Specifically, it requires
     * clients to subscribe to this attribute and not to cache attribute handles
     * between connections unless the devices are bonded. If the application
     * does not need to change the structure of the GATT server attributes at
     * runtime this adds unnecessary complexity to the interaction with peer
     * clients. If the SoftDevice is enabled with the Service Changed
     * Characteristics turned off, then clients are allowed to cache attribute
     * handles making applications simpler on both sides.
     */
    static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = true;

    ble_enable_params_t ble_enable_params;
    uint32_t err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
                                                    PERIPHERAL_LINK_COUNT,
                                                    &ble_enable_params);

    ble_enable_params.gatts_enable_params.attr_tab_size  = GATTS_ATTR_TAB_SIZE;
    ble_enable_params.gatts_enable_params.service_changed  = IS_SRVC_CHANGED_CHARACT_PRESENT;
    ble_enable_params.common_enable_params.vs_uuid_count = UUID_TABLE_MAX_ENTRIES;

    if(err_code  != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

    if (softdevice_enable(&ble_enable_params) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

#if  (NRF_SD_BLE_API_VERSION <= 2)
    ble_gap_addr_t addr;
    if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }
    if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }
#else

#endif

    ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
    ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));

    return btle_gap_init();
}

static void btle_handler(ble_evt_t *p_ble_evt)
{
    using ble::pal::vendor::nordic::nRF5XGattClient;
    using ble::pal::vendor::nordic::nRF5xSecurityManager;

    /* Library service handlers */
#if SDK_CONN_PARAMS_MODULE_ENABLE
    ble_conn_params_on_ble_evt(p_ble_evt);
#endif

#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
#else
    // Forward BLE events to the Connection State module.
    // This must be called before any event handler that uses this module.
    ble_conn_state_on_ble_evt(p_ble_evt);
#endif

#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
    nRF5XGattClient::handle_events(p_ble_evt);
#endif

    nRF5xn               &ble             = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
    nRF5xGap             &gap             = (nRF5xGap &) ble.getGap();
    nRF5xGattServer      &gattServer      = (nRF5xGattServer &) ble.getGattServer();
    nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();

    /* Custom event handler */
    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED: {
            Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110)
            /* Only peripheral role is supported by S110 */
            Gap::Role_t role = Gap::PERIPHERAL;
#else
            Gap::Role_t role = static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role);
#endif
            gap.setConnectionHandle(handle);
            const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
            const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
#if  (NRF_SD_BLE_API_VERSION <= 2)
            const ble_gap_addr_t *own  = &p_ble_evt->evt.gap_evt.params.connected.own_addr;

            gap.processConnectionEvent(handle,
                                       role,
                                       static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
                                       static_cast<BLEProtocol::AddressType_t>(own->addr_type),  own->addr,
                                       params);
#else
            Gap::AddressType_t addr_type;
            Gap::Address_t     own_address;
            gap.getAddress(&addr_type, own_address);

            gap.processConnectionEvent(handle,
                                       role,
                                       static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
                                       addr_type,  own_address,
                                       params);
#endif
            break;
        }

        case BLE_GAP_EVT_DISCONNECTED: {
            Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
            // Since we are not in a connection and have not started advertising,
            // store bonds
            gap.setConnectionHandle (BLE_CONN_HANDLE_INVALID);

            Gap::DisconnectionReason_t reason;
            switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) {
                case BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION:
                    reason = Gap::LOCAL_HOST_TERMINATED_CONNECTION;
                    break;
                case BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION:
                    reason = Gap::REMOTE_USER_TERMINATED_CONNECTION;
                    break;
                case BLE_HCI_CONN_INTERVAL_UNACCEPTABLE:
                    reason = Gap::CONN_INTERVAL_UNACCEPTABLE;
                    break;
                default:
                    /* Please refer to the underlying transport library for an
                     * interpretion of this reason's value. */
                    reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
                    break;
            }

#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
            // Close all pending discoveries for this connection
            nRF5XGattClient::handle_connection_termination(handle);
#endif

            gap.processDisconnectionEvent(handle, reason);
            break;
        }

        case BLE_GAP_EVT_TIMEOUT:
            gap.processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
            break;

        case BLE_GATTC_EVT_TIMEOUT:
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server and Client timeout events.
            // ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle,
            // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
            break;

        case BLE_GAP_EVT_ADV_REPORT: {
            const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report;
            gap.processAdvertisementReport(advReport->peer_addr.addr,
                                           advReport->rssi,
                                           advReport->scan_rsp,
                                           static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
                                           advReport->dlen,
                                           advReport->data,
                                           static_cast<BLEProtocol::AddressType_t>(advReport->peer_addr.addr_type));
            break;
        }

        default:
            break;
    }

    // Process security manager events
    securityManager.sm_handler(p_ble_evt);

    gattServer.hwCallback(p_ble_evt);
}

/*! @brief      Callback when an error occurs inside the SoftDevice */
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
{
    ASSERT_TRUE(false, (void) 0);
}

/*!
    @brief      Handler for general errors above the SoftDevice layer.
                Typically we can' recover from this so we do a reset.
*/
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
{
    ASSERT_STATUS_RET_VOID( error_code );
    NVIC_SystemReset();
}
<commit_msg>BLE: Fix reference to security manager in Nordic event handler.<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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 "common/common.h"
#include "nordic_common.h"

#include "btle.h"
#include "btle_clock.h"

#include "ble_flash.h"
#include "ble_conn_params.h"

#include "btle_gap.h"
#include "custom/custom_helper.h"

#include "ble/GapEvents.h"
#include "nRF5xn.h"

#ifdef S110
    #define IS_LEGACY_DEVICE_MANAGER_ENABLED 1
#elif defined(S130) || defined(S132)
    #define IS_LEGACY_DEVICE_MANAGER_ENABLED 0
#endif

extern "C" {
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
    #include "pstorage.h"
#else
    #include "fstorage.h"
    #include "fds.h"
    #include "ble_conn_state.h"
#endif

#include "softdevice_handler.h"
#include "ble_stack_handler_types.h"
}

#include "nrf_ble_hci.h"

#include "nRF5XPalGattClient.h"
#include "nRF5XPalSecurityManager.h"

bool isEventsSignaled = false;

extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
void            app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector.

static void btle_handler(ble_evt_t *p_ble_evt);

static void sys_evt_dispatch(uint32_t sys_evt)
{
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
    pstorage_sys_event_handler(sys_evt);
#else
    // Forward Softdevice events to the fstorage module
    fs_sys_event_handler(sys_evt);
#endif
}

/**
 * This function is called in interrupt context to handle BLE events; i.e. pull
 * system and user events out of the pending events-queue of the BLE stack. The
 * BLE stack signals the availability of events by the triggering the SWI2
 * interrupt, which forwards the handling to this function.
 *
 * The event processing loop is implemented in intern_softdevice_events_execute().
 *
 * This function will signal to the user code by calling signalEventsToProcess
 * that their is events to process and BLE::processEvents should be called.
 */
static uint32_t signalEvent()
{
    if(isEventsSignaled == false) {
        isEventsSignaled = true;
        nRF5xn::Instance(BLE::DEFAULT_INSTANCE).signalEventsToProcess(BLE::DEFAULT_INSTANCE);
    }
    return NRF_SUCCESS;
}

error_t btle_init(void)
{
    nrf_clock_lf_cfg_t clockConfiguration;

    // register softdevice handler vector
    NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);

    // Configure the LF clock according to values provided by btle_clock.h.
    // It is input from the chain of the yotta configuration system.
    clockConfiguration.source        = LFCLK_CONF_SOURCE;
    clockConfiguration.xtal_accuracy = LFCLK_CONF_ACCURACY;
    clockConfiguration.rc_ctiv       = LFCLK_CONF_RC_CTIV;
    clockConfiguration.rc_temp_ctiv  = LFCLK_CONF_RC_TEMP_CTIV;

    SOFTDEVICE_HANDLER_INIT(&clockConfiguration, signalEvent);

    // Enable BLE stack
    /**
     * Using this call, the application can select whether to include the
     * Service Changed characteristic in the GATT Server. The default in all
     * previous releases has been to include the Service Changed characteristic,
     * but this affects how GATT clients behave. Specifically, it requires
     * clients to subscribe to this attribute and not to cache attribute handles
     * between connections unless the devices are bonded. If the application
     * does not need to change the structure of the GATT server attributes at
     * runtime this adds unnecessary complexity to the interaction with peer
     * clients. If the SoftDevice is enabled with the Service Changed
     * Characteristics turned off, then clients are allowed to cache attribute
     * handles making applications simpler on both sides.
     */
    static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = true;

    ble_enable_params_t ble_enable_params;
    uint32_t err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
                                                    PERIPHERAL_LINK_COUNT,
                                                    &ble_enable_params);

    ble_enable_params.gatts_enable_params.attr_tab_size  = GATTS_ATTR_TAB_SIZE;
    ble_enable_params.gatts_enable_params.service_changed  = IS_SRVC_CHANGED_CHARACT_PRESENT;
    ble_enable_params.common_enable_params.vs_uuid_count = UUID_TABLE_MAX_ENTRIES;

    if(err_code  != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

    if (softdevice_enable(&ble_enable_params) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }

#if  (NRF_SD_BLE_API_VERSION <= 2)
    ble_gap_addr_t addr;
    if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }
    if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
        return ERROR_INVALID_PARAM;
    }
#else

#endif

    ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
    ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));

    return btle_gap_init();
}

static void btle_handler(ble_evt_t *p_ble_evt)
{
    using ble::pal::vendor::nordic::nRF5XGattClient;
    using ble::pal::vendor::nordic::nRF5xSecurityManager;

    /* Library service handlers */
#if SDK_CONN_PARAMS_MODULE_ENABLE
    ble_conn_params_on_ble_evt(p_ble_evt);
#endif

#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
#else
    // Forward BLE events to the Connection State module.
    // This must be called before any event handler that uses this module.
    ble_conn_state_on_ble_evt(p_ble_evt);
#endif

#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
    nRF5XGattClient::handle_events(p_ble_evt);
#endif

    nRF5xn               &ble             = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
    nRF5xGap             &gap             = (nRF5xGap &) ble.getGap();
    nRF5xGattServer      &gattServer      = (nRF5xGattServer &) ble.getGattServer();
    nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager();

    /* Custom event handler */
    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED: {
            Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110)
            /* Only peripheral role is supported by S110 */
            Gap::Role_t role = Gap::PERIPHERAL;
#else
            Gap::Role_t role = static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role);
#endif
            gap.setConnectionHandle(handle);
            const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
            const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
#if  (NRF_SD_BLE_API_VERSION <= 2)
            const ble_gap_addr_t *own  = &p_ble_evt->evt.gap_evt.params.connected.own_addr;

            gap.processConnectionEvent(handle,
                                       role,
                                       static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
                                       static_cast<BLEProtocol::AddressType_t>(own->addr_type),  own->addr,
                                       params);
#else
            Gap::AddressType_t addr_type;
            Gap::Address_t     own_address;
            gap.getAddress(&addr_type, own_address);

            gap.processConnectionEvent(handle,
                                       role,
                                       static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
                                       addr_type,  own_address,
                                       params);
#endif
            break;
        }

        case BLE_GAP_EVT_DISCONNECTED: {
            Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
            // Since we are not in a connection and have not started advertising,
            // store bonds
            gap.setConnectionHandle (BLE_CONN_HANDLE_INVALID);

            Gap::DisconnectionReason_t reason;
            switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) {
                case BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION:
                    reason = Gap::LOCAL_HOST_TERMINATED_CONNECTION;
                    break;
                case BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION:
                    reason = Gap::REMOTE_USER_TERMINATED_CONNECTION;
                    break;
                case BLE_HCI_CONN_INTERVAL_UNACCEPTABLE:
                    reason = Gap::CONN_INTERVAL_UNACCEPTABLE;
                    break;
                default:
                    /* Please refer to the underlying transport library for an
                     * interpretion of this reason's value. */
                    reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
                    break;
            }

#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
            // Close all pending discoveries for this connection
            nRF5XGattClient::handle_connection_termination(handle);
#endif

            gap.processDisconnectionEvent(handle, reason);
            break;
        }

        case BLE_GAP_EVT_TIMEOUT:
            gap.processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
            break;

        case BLE_GATTC_EVT_TIMEOUT:
        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server and Client timeout events.
            // ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle,
            // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
            break;

        case BLE_GAP_EVT_ADV_REPORT: {
            const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report;
            gap.processAdvertisementReport(advReport->peer_addr.addr,
                                           advReport->rssi,
                                           advReport->scan_rsp,
                                           static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
                                           advReport->dlen,
                                           advReport->data,
                                           static_cast<BLEProtocol::AddressType_t>(advReport->peer_addr.addr_type));
            break;
        }

        default:
            break;
    }

    // Process security manager events
    securityManager.sm_handler(p_ble_evt);

    gattServer.hwCallback(p_ble_evt);
}

/*! @brief      Callback when an error occurs inside the SoftDevice */
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
{
    ASSERT_TRUE(false, (void) 0);
}

/*!
    @brief      Handler for general errors above the SoftDevice layer.
                Typically we can' recover from this so we do a reset.
*/
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
{
    ASSERT_STATUS_RET_VOID( error_code );
    NVIC_SystemReset();
}
<|endoftext|>


<commit_before>//==============================================================================
// CellML Model Repository window
//==============================================================================

#include "cellmlmodelrepositorywindow.h"
#include "cellmlmodelrepositorywidget.h"
#include "coreutils.h"

//==============================================================================

#include "ui_cellmlmodelrepositorywindow.h"

//==============================================================================

#include <QClipboard>
#include <QMenu>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>

//==============================================================================

#include <QJsonParser>

//==============================================================================

namespace OpenCOR {
namespace CellMLModelRepository {

//==============================================================================

CellmlModelRepositoryWindow::CellmlModelRepositoryWindow(QWidget *pParent) :
    OrganisationWidget(pParent),
    mGui(new Ui::CellmlModelRepositoryWindow)
{
    // Set up the GUI

    mGui->setupUi(this);

    // Make the name value our focus proxy

    setFocusProxy(mGui->nameValue);

    // Create and add the CellML Model Repository widget

    mCellmlModelRepositoryWidget = new CellmlModelRepositoryWidget(this);

    mGui->dockWidgetContents->layout()->addWidget(mCellmlModelRepositoryWidget);

    // We want our own context menu for the help widget (indeed, we don't want
    // the default one which has the reload menu item and not the other actions
    // that we have in our toolbar, so...)

    mCellmlModelRepositoryWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(mCellmlModelRepositoryWidget, SIGNAL(customContextMenuRequested(const QPoint &)),
            this, SLOT(customContextMenu(const QPoint &)));

    // Retrieve the list of models in the CellML Model Repository as JSON code
    // from http://models.cellml.org/workspace/rest/contents.json

    mNetworkAccessManager = new QNetworkAccessManager(this);

    // Make sure that we get told when the download of our Internet file is
    // complete

    connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply *)),
            this, SLOT(finished(QNetworkReply *)) );

    // Get the list of CellML models

    on_refreshButton_clicked();
}

//==============================================================================

CellmlModelRepositoryWindow::~CellmlModelRepositoryWindow()
{
    // Delete the GUI

    delete mGui;
}

//==============================================================================

void CellmlModelRepositoryWindow::retranslateUi()
{
    // Retranslate the whole window

    mGui->retranslateUi(this);

    // Retranslate our list of models

    outputModelList(mModelList);
}

//==============================================================================

void CellmlModelRepositoryWindow::outputModelList(const QStringList &pModelList)
{
    // Output a given list of models

    mModelList = pModelList;

    QString contents = "";
    const QString leadingSpaces = "        ";

    if (mModelList.count()) {
        // We have models to list, so...

        if (mModelList.count() == 1)
            contents = tr("1 CellML model was found:")+"\n";
        else
            contents = tr("%1 CellML models were found:").arg(mModelList.count())+"\n";

        contents += leadingSpaces+"
\n";

        foreach (const QString &model, mModelList)
            contents += leadingSpaces+"
"+model+"
\n";

        contents += leadingSpaces+"
";
    } else if (mModelNames.empty()) {
        if (mErrorMsg.size()) {
            // Something went wrong while trying to retrieve the list of models,
            // so...

            QString errorMsg = mErrorMsg.left(1).toLower()+mErrorMsg.right(mErrorMsg.size()-1);
            QString dots = (errorMsg.at(errorMsg.size()-1) == '.')?"..":"...";

            contents = leadingSpaces+"Error: "+errorMsg+dots;
        } else {
            // The list is still being loaded, so...

            contents = leadingSpaces+tr("Please wait while the list of CellML models is being loaded...");
        }
    } else {
        // No model could be found, so...

        contents = leadingSpaces+tr("No CellML model matches your criteria");
    }

    // Output the list matching the search criteria, or a message telling the
    // user what went wrong, if anything

    mCellmlModelRepositoryWidget->output(contents);
}

//==============================================================================

void CellmlModelRepositoryWindow::on_nameValue_textChanged(const QString &text)
{
    // Generate a Web page that contains all the models which match our search
    // criteria

    outputModelList(mModelNames.filter(QRegExp(text, Qt::CaseInsensitive,
                                               QRegExp::RegExp2)));
}

//==============================================================================

void CellmlModelRepositoryWindow::on_actionCopy_triggered()
{
    // Copy the current slection to the clipboard

    QApplication::clipboard()->setText(mCellmlModelRepositoryWidget->selectedText());
}

//==============================================================================

void CellmlModelRepositoryWindow::on_refreshButton_clicked()
{
    // Output the message telling the user that the list is being downloaded
    // Note: to clear mModelNames ensures that we get the correct message from
    //       outputModelList...

    mModelNames.clear();

    outputModelList(QStringList());

    // Disable the GUI side, so that the user doesn't get confused and ask to
    // refresh over and over again while he should just be patient

    setEnabled(false);

    // Get the list of CellML models

    mNetworkAccessManager->get(QNetworkRequest(QUrl("http://models.cellml.org/workspace/rest/contents.json")));
}

//==============================================================================

void CellmlModelRepositoryWindow::finished(QNetworkReply *pNetworkReply)
{
    // Clear some properties

    mModelNames.clear();
    mModelUrls.clear();

    mErrorMsg.clear();

    // Output the list of models, should we have retrieved it without any
    // problem

    if (pNetworkReply->error() == QNetworkReply::NoError) {
        // Parse the JSON code

        QJson::Parser jsonParser;
        bool parsingOk;

        QVariantMap res = jsonParser.parse (pNetworkReply->readAll(), &parsingOk).toMap();

        if (parsingOk) {
            // Retrieve the name of the keys

            QStringList keys;

            foreach (const QVariant &keyVariant, res["keys"].toList())
                keys << keyVariant.toString();

            // Retrieve the list of models itself

            foreach (const QVariant &modelVariant, res["values"].toList()) {
                QVariantList modelDetailsVariant = modelVariant.toList();

                mModelNames << modelDetailsVariant.at(0).toString();
                mModelUrls << modelDetailsVariant.at(1).toString();
            }
        }
    } else {
        // Something went wrong, so...

        mErrorMsg = pNetworkReply->errorString();
    }

    // Initialise the output using whatever search criteria is present

    on_nameValue_textChanged(mGui->nameValue->text());

    // Re-enable the GUI side

    setEnabled(true);

    // Give, within the current window, the focus to mGui->nameValue, but only
    // if the current window already has the focus

    Core::setFocusTo(mGui->nameValue);
}

//==============================================================================

void CellmlModelRepositoryWindow::customContextMenu(const QPoint &) const
{
    // Create a custom context menu for our CellML Models Repository widget

    QMenu menu;

    menu.addAction(mGui->actionCopy);

    menu.exec(QCursor::pos());
}

//==============================================================================

}   // namespace CellMLModelRepository
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Some minor cleaning up (#57).<commit_after>//==============================================================================
// CellML Model Repository window
//==============================================================================

#include "cellmlmodelrepositorywindow.h"
#include "cellmlmodelrepositorywidget.h"
#include "coreutils.h"

//==============================================================================

#include "ui_cellmlmodelrepositorywindow.h"

//==============================================================================

#include <QClipboard>
#include <QMenu>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>

//==============================================================================

#include <QJsonParser>

//==============================================================================

namespace OpenCOR {
namespace CellMLModelRepository {

//==============================================================================

CellmlModelRepositoryWindow::CellmlModelRepositoryWindow(QWidget *pParent) :
    OrganisationWidget(pParent),
    mGui(new Ui::CellmlModelRepositoryWindow)
{
    // Set up the GUI

    mGui->setupUi(this);

    // Make the name value our focus proxy

    setFocusProxy(mGui->nameValue);

    // Create and add the CellML Model Repository widget

    mCellmlModelRepositoryWidget = new CellmlModelRepositoryWidget(this);

    mGui->dockWidgetContents->layout()->addWidget(mCellmlModelRepositoryWidget);

    // We want our own context menu for the help widget (indeed, we don't want
    // the default one which has the reload menu item and not the other actions
    // that we have in our toolbar, so...)

    mCellmlModelRepositoryWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(mCellmlModelRepositoryWidget, SIGNAL(customContextMenuRequested(const QPoint &)),
            this, SLOT(customContextMenu(const QPoint &)));

    // Retrieve the list of models in the CellML Model Repository as JSON code
    // from http://models.cellml.org/workspace/rest/contents.json

    mNetworkAccessManager = new QNetworkAccessManager(this);

    // Make sure that we get told when the download of our Internet file is
    // complete

    connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply *)),
            this, SLOT(finished(QNetworkReply *)) );

    // Get the list of CellML models

    on_refreshButton_clicked();
}

//==============================================================================

CellmlModelRepositoryWindow::~CellmlModelRepositoryWindow()
{
    // Delete the GUI

    delete mGui;
}

//==============================================================================

void CellmlModelRepositoryWindow::retranslateUi()
{
    // Retranslate the whole window

    mGui->retranslateUi(this);

    // Retranslate our list of models

    outputModelList(mModelList);
}

//==============================================================================

void CellmlModelRepositoryWindow::outputModelList(const QStringList &pModelList)
{
    // Output a given list of models

    mModelList = pModelList;

    QString contents = "";
    const QString leadingSpaces = "        ";

    if (mModelList.count()) {
        // We have models to list, so...

        if (mModelList.count() == 1)
            contents = tr("1 CellML model was found:")+"\n";
        else
            contents = tr("%1 CellML models were found:").arg(mModelList.count())+"\n";

        contents += leadingSpaces+"
\n";

        foreach (const QString &model, mModelList)
            contents += leadingSpaces+"
"+model+"
\n";

        contents += leadingSpaces+"
";
    } else if (mModelNames.empty()) {
        if (mErrorMsg.size()) {
            // Something went wrong while trying to retrieve the list of models,
            // so...

            QString errorMsg = mErrorMsg.left(1).toLower()+mErrorMsg.right(mErrorMsg.size()-1);
            QString dots = (errorMsg.at(errorMsg.size()-1) == '.')?"..":"...";

            contents = leadingSpaces+"Error: "+errorMsg+dots;
        } else {
            // The list is still being loaded, so...

            contents = leadingSpaces+tr("Please wait while the list of CellML models is being loaded...");
        }
    } else {
        // No model could be found, so...

        contents = leadingSpaces+tr("No CellML model matches your criteria");
    }

    // Output the list matching the search criteria, or a message telling the
    // user what went wrong, if anything

    mCellmlModelRepositoryWidget->output(contents);
}

//==============================================================================

void CellmlModelRepositoryWindow::on_nameValue_textChanged(const QString &text)
{
    // Generate a Web page that contains all the models which match our search
    // criteria

    outputModelList(mModelNames.filter(QRegExp(text, Qt::CaseInsensitive)));
}

//==============================================================================

void CellmlModelRepositoryWindow::on_actionCopy_triggered()
{
    // Copy the current slection to the clipboard

    QApplication::clipboard()->setText(mCellmlModelRepositoryWidget->selectedText());
}

//==============================================================================

void CellmlModelRepositoryWindow::on_refreshButton_clicked()
{
    // Output the message telling the user that the list is being downloaded
    // Note: to clear mModelNames ensures that we get the correct message from
    //       outputModelList...

    mModelNames.clear();

    outputModelList(QStringList());

    // Disable the GUI side, so that the user doesn't get confused and ask to
    // refresh over and over again while he should just be patient

    setEnabled(false);

    // Get the list of CellML models

    mNetworkAccessManager->get(QNetworkRequest(QUrl("http://models.cellml.org/workspace/rest/contents.json")));
}

//==============================================================================

void CellmlModelRepositoryWindow::finished(QNetworkReply *pNetworkReply)
{
    // Clear some properties

    mModelNames.clear();
    mModelUrls.clear();

    mErrorMsg.clear();

    // Output the list of models, should we have retrieved it without any
    // problem

    if (pNetworkReply->error() == QNetworkReply::NoError) {
        // Parse the JSON code

        QJson::Parser jsonParser;
        bool parsingOk;

        QVariantMap res = jsonParser.parse (pNetworkReply->readAll(), &parsingOk).toMap();

        if (parsingOk) {
            // Retrieve the name of the keys

            QStringList keys;

            foreach (const QVariant &keyVariant, res["keys"].toList())
                keys << keyVariant.toString();

            // Retrieve the list of models itself

            foreach (const QVariant &modelVariant, res["values"].toList()) {
                QVariantList modelDetailsVariant = modelVariant.toList();

                mModelNames << modelDetailsVariant.at(0).toString();
                mModelUrls << modelDetailsVariant.at(1).toString();
            }
        }
    } else {
        // Something went wrong, so...

        mErrorMsg = pNetworkReply->errorString();
    }

    // Initialise the output using whatever search criteria is present

    on_nameValue_textChanged(mGui->nameValue->text());

    // Re-enable the GUI side

    setEnabled(true);

    // Give, within the current window, the focus to mGui->nameValue, but only
    // if the current window already has the focus

    Core::setFocusTo(mGui->nameValue);
}

//==============================================================================

void CellmlModelRepositoryWindow::customContextMenu(const QPoint &) const
{
    // Create a custom context menu for our CellML Models Repository widget

    QMenu menu;

    menu.addAction(mGui->actionCopy);

    menu.exec(QCursor::pos());
}

//==============================================================================

}   // namespace CellMLModelRepository
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>#include "BuildingQueue.h"
#include "bwem.h"

#include "UnitManager.h"
#include "BaseManager.h"
#include "BuildingPlacer.h"
#include "DrawingManager.h"

Neolib::BuildingQueue buildingQueue;

namespace Neolib {

	void BuildingQueue::onFrame() {
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->buildingType.getRace() == BWAPI::Races::Terran && !it->builder) {

			}

			if (it->builder) {
				auto order = it->builder->getOrder();
				if (order == BWAPI::Orders::ConstructingBuilding)
					continue;
				else if (order == BWAPI::Orders::PlaceBuilding)
					continue;
				if (resourceManager.canAfford(it->buildingType)) {
					if (it->buildingUnit) {
						it->builder->rightClick(it->buildingUnit);
					}
					else {
						it->builder->build(it->buildingType, it->designatedLocation);
					}
				}
			}
		}
	}

	void BuildingQueue::onUnitComplete(BWAPI::Unit unit) {
		// Check if our building is done
		for (auto it = buildingQueue.begin(); it != buildingQueue.end();) {
			if (it->buildingUnit == unit) {
				if (it->buildingType.getRace() == BWAPI::Races::Terran && it->builder)
					baseManager.giveBackUnit(it->builder);
				it = buildingQueue.erase(it);
			} else {
				++it;
			}
		}
	}

	void BuildingQueue::onUnitCreate(BWAPI::Unit unit) {
		// If our building was placed
		for (auto &o : buildingQueue) {
			if (o.buildingType == unit->getType() && o.designatedLocation == unit->getTilePosition()) {
				o.buildingUnit = unit;
			}
		}
	}

	void BuildingQueue::onUnitDestroy(BWAPI::Unit unit) {
		// Check if our builder died
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->builder == unit) {
				// Find replacement builder
				it->builder = baseManager.findClosestBuilder(it->buildingType.whatBuilds().first, (BWAPI::Position)it->designatedLocation);
				if (it->builder) {
					baseManager.takeUnit(it->builder);
					if (it->buildingUnit && it->buildingUnit->exists()) {
						it->builder->rightClick(it->buildingUnit);
					}
					if (!it->buildingUnit) {
						it->builder->build(it->buildingType, it->designatedLocation);
					}
				}
			}
		}

		// Check if our building died
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->buildingUnit == unit) {
				it->buildingUnit = nullptr;
				if (it->builder && it->builder->exists())
					it->builder->build(it->buildingType, it->designatedLocation);
			}
		}
	}

	void BuildingQueue::onUnitMorph(BWAPI::Unit unit) {
		onUnitCreate(unit);
	}

	bool BuildingQueue::doBuild(BWAPI::UnitType building, BWAPI::TilePosition at, BWAPI::Unit u) {
		if (at == BWAPI::TilePositions::None) {
			if (!u && !(u = baseManager.findBuilder(building))) // Could not a find builder
				return false;
			at = buildingPlacer.getBuildLocation(building, u->getTilePosition());
			if (at == BWAPI::TilePositions::None) {
				drawingManager.failedLocations.insert({ at, building });
				BWAPI::Broodwar->pingMinimap((BWAPI::Position)at);
				return false;
			}
		}
		else
			if (!u && !(u = baseManager.findClosestBuilder(building, (BWAPI::Position) at))) // Could not a find builder
				return false;

		// If build location intersects another build location, nope out
		BWAPI::TilePosition buildingEnd(at + building.tileSize());
		for (auto &o : buildingQueue) {
			BWAPI::TilePosition otherEnd(o.designatedLocation + o.buildingType.tileSize());
			if (at.x < o.designatedLocation.x) {
				if (at.y < o.designatedLocation.y) {
					if (o.designatedLocation.x < buildingEnd.x && o.designatedLocation.y < buildingEnd.y)
						return false;
					else if (o.designatedLocation.x < buildingEnd.x && at.y < otherEnd.y)
						return false;
				}
			}
			else {
				if (at.y < o.designatedLocation.y) {
					if (at.x < otherEnd.x && o.designatedLocation.y < buildingEnd.y)
						return false;
				}
				else if (at.x < otherEnd.x && at.y < otherEnd.y)
						return false;
			}
		}

		if (u)
			baseManager.takeUnit(u);

		if (u->build(building, at)) {
			ConstructionProject cp;
			cp.builder = u;
			cp.buildingType = building;
			cp.designatedLocation = at;

			buildingQueue.emplace_back(cp);
			return true;
		}
		else {
			if (!BWAPI::Broodwar->isVisible(at))
				u->move((BWAPI::Position)at);
			drawingManager.failedLocations.insert({ at, building });
			BWAPI::Broodwar->pingMinimap((BWAPI::Position)at);
			return false;
		}
	}

	ResourceCount BuildingQueue::getQueuedResources() const {
		ResourceCount resourceCount;

		for (auto &o : this->buildingQueue)
			if (!o.buildingUnit)
				resourceCount += o.buildingType;

		return resourceCount;
	}

	SupplyCount BuildingQueue::getQueuedSupply(bool countResourceDepots) const {
		SupplyCount supplyCount;
		for (auto &o : buildingQueue) {
			// Terran
			if (o.buildingType == BWAPI::UnitTypes::Terran_Supply_Depot)
				supplyCount.terran += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Terran_Command_Center && countResourceDepots)
				supplyCount.terran += 20;

			// Protoss
			else if (o.buildingType == BWAPI::UnitTypes::Protoss_Pylon)
				supplyCount.protoss += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Protoss_Nexus && countResourceDepots)
				supplyCount.protoss += 18;

			// Zerg
			else if (o.buildingType == BWAPI::UnitTypes::Zerg_Overlord)
				supplyCount.zerg += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Zerg_Hatchery && countResourceDepots)
				supplyCount.zerg += 2;
		}

		return supplyCount;
	}

	bool BuildingQueue::isWorkerBuilding(BWAPI::Unit u) const {
		for (auto &o : buildingQueue)
			if (o.builder == u)
				return true;
		return false;
	}

	const std::list <ConstructionProject> &BuildingQueue::buildingsQueued() {
		return buildingQueue;
	}

}
<commit_msg>Let's see how aggroing for building workers work<commit_after>#include "BuildingQueue.h"
#include "bwem.h"

#include "UnitManager.h"
#include "BaseManager.h"
#include "BuildingPlacer.h"
#include "DrawingManager.h"

Neolib::BuildingQueue buildingQueue;

namespace Neolib {

	void BuildingQueue::onFrame() {
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->buildingType.getRace() == BWAPI::Races::Terran && !it->builder) {

			}

			if (it->builder) {
				auto order = it->builder->getOrder();
				if (order == BWAPI::Orders::ConstructingBuilding)
					continue;
				else if (order == BWAPI::Orders::PlaceBuilding)
					continue;
				if (resourceManager.canAfford(it->buildingType)) {
					if (it->buildingUnit) {
						it->builder->rightClick(it->buildingUnit);
					}
					else {
						it->builder->build(it->buildingType, it->designatedLocation);
					}
				}
			}
		}
	}

	void BuildingQueue::onUnitComplete(BWAPI::Unit unit) {
		// Check if our building is done
		for (auto it = buildingQueue.begin(); it != buildingQueue.end();) {
			if (it->buildingUnit == unit) {
				if (it->buildingType.getRace() == BWAPI::Races::Terran && it->builder)
					baseManager.giveBackUnit(it->builder);
				it = buildingQueue.erase(it);
			} else {
				++it;
			}
		}
	}

	void BuildingQueue::onUnitCreate(BWAPI::Unit unit) {
		// If our building was placed
		for (auto &o : buildingQueue) {
			if (o.buildingType == unit->getType() && o.designatedLocation == unit->getTilePosition()) {
				o.buildingUnit = unit;
			}
		}
	}

	void BuildingQueue::onUnitDestroy(BWAPI::Unit unit) {
		// Check if our builder died
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->builder == unit) {
				// Find replacement builder
				it->builder = baseManager.findClosestBuilder(it->buildingType.whatBuilds().first, (BWAPI::Position)it->designatedLocation);
				if (it->builder) {
					baseManager.takeUnit(it->builder);
					if (it->buildingUnit && it->buildingUnit->exists()) {
						it->builder->rightClick(it->buildingUnit);
					}
					if (!it->buildingUnit) {
						it->builder->build(it->buildingType, it->designatedLocation);
					}
				}
			}
		}

		// Check if our building died
		for (auto it = buildingQueue.begin(); it != buildingQueue.end(); ++it) {
			if (it->buildingUnit == unit) {
				it->buildingUnit = nullptr;
				if (it->builder && it->builder->exists())
					it->builder->build(it->buildingType, it->designatedLocation);
			}
		}
	}

	void BuildingQueue::onUnitMorph(BWAPI::Unit unit) {
		onUnitCreate(unit);
	}

	bool BuildingQueue::doBuild(BWAPI::UnitType building, BWAPI::TilePosition at, BWAPI::Unit u) {
		if (at == BWAPI::TilePositions::None) {
			if (!u && !(u = baseManager.findBuilder(building))) // Could not a find builder
				return false;
			at = buildingPlacer.getBuildLocation(building, u->getTilePosition());
			if (at == BWAPI::TilePositions::None) {
				drawingManager.failedLocations.insert({ at, building });
				BWAPI::Broodwar->pingMinimap((BWAPI::Position)at);
				return false;
			}
		}
		else
			if (!u && !(u = baseManager.findClosestBuilder(building, (BWAPI::Position) at))) // Could not a find builder
				return false;

		// If build location intersects another build location, nope out
		BWAPI::TilePosition buildingEnd(at + building.tileSize());
		for (auto &o : buildingQueue) {
			BWAPI::TilePosition otherEnd(o.designatedLocation + o.buildingType.tileSize());
			if (at.x < o.designatedLocation.x) {
				if (at.y < o.designatedLocation.y) {
					if (o.designatedLocation.x < buildingEnd.x && o.designatedLocation.y < buildingEnd.y)
						return false;
					else if (o.designatedLocation.x < buildingEnd.x && at.y < otherEnd.y)
						return false;
				}
			}
			else {
				if (at.y < o.designatedLocation.y) {
					if (at.x < otherEnd.x && o.designatedLocation.y < buildingEnd.y)
						return false;
				}
				else if (at.x < otherEnd.x && at.y < otherEnd.y)
						return false;
			}
		}

		//if (u)
		//	baseManager.takeUnit(u);

		if (u->build(building, at)) {
			ConstructionProject cp;
			cp.builder = u;
			cp.buildingType = building;
			cp.designatedLocation = at;

			buildingQueue.emplace_back(cp);
			return true;
		}
		else {
			if (!BWAPI::Broodwar->isVisible(at))
				u->move((BWAPI::Position)at);
			drawingManager.failedLocations.insert({ at, building });
			BWAPI::Broodwar->pingMinimap((BWAPI::Position)at);
			return false;
		}
	}

	ResourceCount BuildingQueue::getQueuedResources() const {
		ResourceCount resourceCount;

		for (auto &o : this->buildingQueue)
			if (!o.buildingUnit)
				resourceCount += o.buildingType;

		return resourceCount;
	}

	SupplyCount BuildingQueue::getQueuedSupply(bool countResourceDepots) const {
		SupplyCount supplyCount;
		for (auto &o : buildingQueue) {
			// Terran
			if (o.buildingType == BWAPI::UnitTypes::Terran_Supply_Depot)
				supplyCount.terran += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Terran_Command_Center && countResourceDepots)
				supplyCount.terran += 20;

			// Protoss
			else if (o.buildingType == BWAPI::UnitTypes::Protoss_Pylon)
				supplyCount.protoss += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Protoss_Nexus && countResourceDepots)
				supplyCount.protoss += 18;

			// Zerg
			else if (o.buildingType == BWAPI::UnitTypes::Zerg_Overlord)
				supplyCount.zerg += 16;
			else if (o.buildingType == BWAPI::UnitTypes::Zerg_Hatchery && countResourceDepots)
				supplyCount.zerg += 2;
		}

		return supplyCount;
	}

	bool BuildingQueue::isWorkerBuilding(BWAPI::Unit u) const {
		for (auto &o : buildingQueue)
			if (o.builder == u)
				return true;
		return false;
	}

	const std::list <ConstructionProject> &BuildingQueue::buildingsQueued() {
		return buildingQueue;
	}

}
<|endoftext|>


<commit_before>// Time:  O(1)
// Space: O(1)

// Thread-Safe, Lazy Initilization
class Solution {
public:
    /**
     * @return: The same instance of this class every time
     */
    static Solution* getInstance() {
        static Solution *instance = new Solution();
        return instance;
    }
private:
    Solution() {}
};<commit_msg>Update singleton.cpp<commit_after>// Time:  O(1)
// Space: O(1)

// Thread-Safe, Lazy Initilization
class Solution {
public:
    /**
     * @return: The same instance of this class every time
     */
    static Solution* getInstance() {
        static Solution *instance = new Solution(); // C++ 11 thread-safe local-static-initialization
        return instance;
    }
private:
    Solution() {}
};
<|endoftext|>