<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

using namespace std;

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CLevelDBBatch batch(&db.GetObfuscateKey());
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(make_pair(DB_COINS, it->first));
            else
                batch.Write(make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    boost::scoped_ptr<CLevelDBIterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
    pcursor->Seek('c');

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    CAmount nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        CCoins coins;
        if (pcursor->GetKey(key) && key.first == 'c') {
            if (pcursor->GetValue(coins)) {
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + pcursor->GetKeySize();
                ss << VARINT(0);
            } else {
                return error("CCoinsViewDB::GetStats() : unable to read value");
            }
        } else {
            break;
        }
        pcursor->Next();
    }
    {
        LOCK(cs_main);
        stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
    }
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CLevelDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CLevelDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair('b', uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == 'b') {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<commit_msg>trivial: use constants for db keys<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

using namespace std;

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CLevelDBBatch batch(&db.GetObfuscateKey());
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(make_pair(DB_COINS, it->first));
            else
                batch.Write(make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    boost::scoped_ptr<CLevelDBIterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
    pcursor->Seek(DB_COINS);

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    CAmount nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        CCoins coins;
        if (pcursor->GetKey(key) && key.first == DB_COINS) {
            if (pcursor->GetValue(coins)) {
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + pcursor->GetKeySize();
                ss << VARINT(0);
            } else {
                return error("CCoinsViewDB::GetStats() : unable to read value");
            }
        } else {
            break;
        }
        pcursor->Next();
    }
    {
        LOCK(cs_main);
        stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
    }
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CLevelDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CLevelDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>#ifndef units_hh_INCLUDED
#define units_hh_INCLUDED

#include <type_traits>

namespace Kakoune
{

template<typename RealType, typename ValueType = int>
class StronglyTypedNumber
{
public:
    explicit constexpr StronglyTypedNumber(ValueType value)
        : m_value(value)
    {
        static_assert(std::is_base_of<StronglyTypedNumber, RealType>::value,
                     "RealType is not derived from StronglyTypedNumber");
    }

    constexpr RealType operator+(const RealType& other) const
    { return RealType(m_value + other.m_value); }

    constexpr RealType operator-(const RealType& other) const
    { return RealType(m_value - other.m_value); }

    constexpr RealType operator*(const RealType& other) const
    { return RealType(m_value * other.m_value); }

    constexpr RealType operator/(const RealType& other) const
    { return RealType(m_value / other.m_value); }

    RealType& operator+=(const RealType& other)
    { m_value += other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator-=(const RealType& other)
    { m_value -= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator*=(const RealType& other)
    { m_value *= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator/=(const RealType& other)
    { m_value /= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator++()
    { ++m_value; return static_cast<RealType&>(*this); }

    RealType& operator--()
    { --m_value; return static_cast<RealType&>(*this); }

    RealType operator++(int)
    { RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; }

    RealType operator--(int)
    { RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; }

    constexpr RealType operator-() { return RealType(-m_value); }

    constexpr bool operator==(const RealType& other) const
    { return m_value == other.m_value; }

    constexpr bool operator!=(const RealType& other) const
    { return m_value != other.m_value; }

    constexpr bool operator<(const RealType& other) const
    { return m_value < other.m_value; }

    constexpr bool operator<=(const RealType& other) const
    { return m_value <= other.m_value; }

    constexpr bool operator>(const RealType& other) const
    { return m_value > other.m_value; }

    constexpr bool operator>=(const RealType& other) const
    { return m_value >= other.m_value; }

    constexpr bool operator!() const
    { return !m_value; }

    explicit constexpr operator ValueType() const { return m_value; }
    explicit constexpr operator bool() const { return m_value; }
private:
   ValueType m_value;
};

struct LineCount : public StronglyTypedNumber<LineCount, int>
{
    constexpr LineCount(int value) : StronglyTypedNumber<LineCount>(value) {}
};

inline constexpr LineCount operator"" _line(unsigned long long int value)
{
    return LineCount(value);
}

struct ByteCount : public StronglyTypedNumber<ByteCount, int>
{
    constexpr ByteCount(int value) : StronglyTypedNumber<ByteCount>(value) {}
};

inline constexpr ByteCount operator"" _byte(unsigned long long int value)
{
    return ByteCount(value);
}

struct CharCount : public StronglyTypedNumber<CharCount, int>
{
    constexpr CharCount(int value) : StronglyTypedNumber<CharCount>(value) {}
};

inline constexpr CharCount operator"" _char(unsigned long long int value)
{
    return CharCount(value);
}

}

#endif // units_hh_INCLUDED

<commit_msg>add default zero construction to units<commit_after>#ifndef units_hh_INCLUDED
#define units_hh_INCLUDED

#include <type_traits>

namespace Kakoune
{

template<typename RealType, typename ValueType = int>
class StronglyTypedNumber
{
public:
    explicit constexpr StronglyTypedNumber(ValueType value)
        : m_value(value)
    {
        static_assert(std::is_base_of<StronglyTypedNumber, RealType>::value,
                     "RealType is not derived from StronglyTypedNumber");
    }

    constexpr RealType operator+(const RealType& other) const
    { return RealType(m_value + other.m_value); }

    constexpr RealType operator-(const RealType& other) const
    { return RealType(m_value - other.m_value); }

    constexpr RealType operator*(const RealType& other) const
    { return RealType(m_value * other.m_value); }

    constexpr RealType operator/(const RealType& other) const
    { return RealType(m_value / other.m_value); }

    RealType& operator+=(const RealType& other)
    { m_value += other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator-=(const RealType& other)
    { m_value -= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator*=(const RealType& other)
    { m_value *= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator/=(const RealType& other)
    { m_value /= other.m_value; return static_cast<RealType&>(*this); }

    RealType& operator++()
    { ++m_value; return static_cast<RealType&>(*this); }

    RealType& operator--()
    { --m_value; return static_cast<RealType&>(*this); }

    RealType operator++(int)
    { RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; }

    RealType operator--(int)
    { RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; }

    constexpr RealType operator-() { return RealType(-m_value); }

    constexpr bool operator==(const RealType& other) const
    { return m_value == other.m_value; }

    constexpr bool operator!=(const RealType& other) const
    { return m_value != other.m_value; }

    constexpr bool operator<(const RealType& other) const
    { return m_value < other.m_value; }

    constexpr bool operator<=(const RealType& other) const
    { return m_value <= other.m_value; }

    constexpr bool operator>(const RealType& other) const
    { return m_value > other.m_value; }

    constexpr bool operator>=(const RealType& other) const
    { return m_value >= other.m_value; }

    constexpr bool operator!() const
    { return !m_value; }

    explicit constexpr operator ValueType() const { return m_value; }
    explicit constexpr operator bool() const { return m_value; }
private:
   ValueType m_value;
};

struct LineCount : public StronglyTypedNumber<LineCount, int>
{
    LineCount() : LineCount(0) {}
    constexpr LineCount(int value) : StronglyTypedNumber<LineCount>(value) {}
};

inline constexpr LineCount operator"" _line(unsigned long long int value)
{
    return LineCount(value);
}

struct ByteCount : public StronglyTypedNumber<ByteCount, int>
{
    ByteCount() : ByteCount(0) {}
    constexpr ByteCount(int value) : StronglyTypedNumber<ByteCount>(value) {}
};

inline constexpr ByteCount operator"" _byte(unsigned long long int value)
{
    return ByteCount(value);
}

struct CharCount : public StronglyTypedNumber<CharCount, int>
{
    CharCount() : CharCount(0) {}
    constexpr CharCount(int value) : StronglyTypedNumber<CharCount>(value) {}
};

inline constexpr CharCount operator"" _char(unsigned long long int value)
{
    return CharCount(value);
}

}

#endif // units_hh_INCLUDED

<|endoftext|>


<commit_before>/**
 * v8cgi - (fast)cgi binary
 */

#include <v8.h>
#include <v8-debug.h>
#include <stdlib.h>
#include <string.h>
#include "app.h"
#include "path.h"

#ifdef FASTCGI
#  include <fcgi_stdio.h>
#  include <signal.h>
#endif

/**
 * Format for command line arguments
 *
 * as you can see if you wish to pass any arguments to v8, you MUST
 * put a -- surrounded by whitespace after all the v8 arguments
 *
 * any arguments after the v8_args but before the program_file are
 * used by v8cgi.
 */
static const char * v8cgi_usage = "v8cgi [v8_args --] [-v] [-h] [-c path] [-d port] program_file [argument ...]";

class v8cgi_CGI : public v8cgi_App {
public:
	/**
	 * Initialize from command line
	 */
	int init(int argc, char ** argv) {
		v8cgi_App::init();

		this->argv0 = (argc > 0 ? path_normalize(argv[0]) : std::string(""));

		if (argc == 1) {
			/* no command-line arguments, try looking for CGI env vars */
			this->fromEnvVars();
		}

		try {
			this->process_args(argc, argv);
		} catch (std::string e) {
			this->error(e.c_str(), __FILE__, __LINE__);
			return 1;
		}

		return 0;
	}

	/**
	 * STDIN reader
	 */
	size_t reader(char * destination, size_t amount) {
		return fread((void *) destination, sizeof(char), amount, stdin);
	}

	/**
	 * STDOUT writer
	 */
	size_t writer(const char * data, size_t amount) {
		return fwrite((void *) data, sizeof(char), amount, stdout);
	}

	/**
	 * STDERR error
	 */
	void error(const char * data, const char * file, int line) {
		fwrite((void *) data, sizeof(char), strlen(data), stderr);
		fwrite((void *) "\n", sizeof(char), 1, stderr);
	}

	/**
	 * STDOUT flush
	 * @return whether successful
	 */
	bool flush() {
		return (fflush(stdout) == 0);
	}

	void fromEnvVars() {
		char * env = getenv("PATH_TRANSLATED");
		if (!env) { env = getenv("SCRIPT_FILENAME"); }
		if (env) { this->mainfile = std::string(env); }
	}

private:
	std::string argv0;

	const char * instanceType() {
		return "cli";
	}

	const char * executableName() {
		return this->argv0.c_str();
	}

	/**
	 * Process command line arguments.
	 */
	void process_args(int argc, char ** argv) {
		std::string err = "Invalid command line usage.\n";
		err += "Correct usage: ";
		err += v8cgi_usage; /* see the v8cgi_usage definition for the format */

		int index = 0;

		/* see if we have v8 options */
		bool have_v8args = false;
		for (; index < argc; ++index) {
			/* FIXME: if there is a standalone "--" after the name of the script
			 then this breaks.  I can't figure out a solution to this, so
			 for now we don't support any standalone "--" after the script name.
			 One solution (and the way it currently works) is to require "--"
			 before all other args even if no v8 args are used, but that seems
			 I don't like this, but it is where we are right now. */
			if (std::string(argv[index]) == "--") {
				/* treat all previous arguments as v8 arguments */
				int v8argc = index;
				v8::V8::SetFlagsFromCommandLine(&v8argc, argv, true);
				index++; /* skip over the "--" */
				have_v8args = true;
				break;
			}
		}

		/* if there were no v8 args, then reset index to the first argument */
		if (!have_v8args) { index = 1; }

		/* scan for v8cgi-specific arguments now */
		while (index < argc) {
			std::string optname(argv[index]);
			if (optname[0] != '-') { break; } /* not starting with "-" => mainfile */
			if (optname.length() != 2) { throw err; } /* one-character options only */
			index++; /* skip the option name */

			switch (optname[1]) {
				case 'c':
					if (index >= argc) { throw err; } /* missing option value */
					this->cfgfile = argv[index];
#ifdef VERBOSE
					printf("cfgfile: %s\n", argv[index]);
#endif
					index++; /* skip the option value */
				break;

				case 'd':
					if (index >= argc) { throw err; } /* missing option value */
					v8::Debug::EnableAgent("v8cgi", atoi(argv[index]));
#ifdef VERBOSE
					printf("port: %s\n", argv[index]);
#endif
					index++; /* skip the option value */
				break;

				case 'h':
					printf(v8cgi_usage);
					printf("\n");
				break;

				case 'v':
					printf("v8cgi version %s", STRING(VERSION));
					printf("\n");
				break;

				default:
					throw err;
				break;
			}

		}

		if (index < argc) {
			/* argv[index] is the program file */
			this->mainfile = argv[index];
			/* expand mainfile to absolute path */
			if (!path_isabsolute(this->mainfile)) {
				std::string tmp = path_getcwd();
				tmp += "/";
				tmp += this->mainfile;
				this->mainfile = path_normalize(this->mainfile);
			}
			index++; /* skip over the program_file */
		}

		/* all the rest of the arguments are arguments to the program_file */
		for (; index < argc; ++index) {
#ifdef VERBOSE
			printf("program_arg: %s\n", argv[index]);
#endif
			this->mainfile_args.push_back(std::string(argv[index]));
		}
	}
};

#ifdef FASTCGI
	/**
	 * This is true only after we receive a signal to terminate
	 */
	void handle_sigterm(int param) {
		FCGI_SetExitStatus(0);
		exit(0);
 	}

	void handle_sigusr1(int param) {
		FCGI_SetExitStatus(0);
		exit(0);
	}
#endif

extern char ** environ;

int main(int argc, char ** argv) {
	int result = 0;
	v8cgi_CGI cgi;
	result = cgi.init(argc, argv);
	if (result) { exit(result); }

#ifdef FASTCGI
	signal(SIGTERM, handle_sigterm);
	signal(SIGUSR1, handle_sigusr1);
	/**
	 * FastCGI main loop
	 */
	while (FCGI_Accept() >= 0) {
		cgi.fromEnvVars();
#endif

		result = cgi.execute(environ);

#ifdef FASTCGI
		FCGI_SetExitStatus(result);
	}
#endif

	return result;
}
<commit_msg>fcgi sigpipe support<commit_after>/**
 * v8cgi - (fast)cgi binary
 */

#include <v8.h>
#include <v8-debug.h>
#include <stdlib.h>
#include <string.h>
#include "app.h"
#include "path.h"

#ifdef FASTCGI
#  include <fcgi_stdio.h>
#  include <signal.h>
#endif

/**
 * Format for command line arguments
 *
 * as you can see if you wish to pass any arguments to v8, you MUST
 * put a -- surrounded by whitespace after all the v8 arguments
 *
 * any arguments after the v8_args but before the program_file are
 * used by v8cgi.
 */
static const char * v8cgi_usage = "v8cgi [v8_args --] [-v] [-h] [-c path] [-d port] program_file [argument ...]";

class v8cgi_CGI : public v8cgi_App {
public:
	/**
	 * Initialize from command line
	 */
	int init(int argc, char ** argv) {
		v8cgi_App::init();

		this->argv0 = (argc > 0 ? path_normalize(argv[0]) : std::string(""));

		if (argc == 1) {
			/* no command-line arguments, try looking for CGI env vars */
			this->fromEnvVars();
		}

		try {
			this->process_args(argc, argv);
		} catch (std::string e) {
			this->error(e.c_str(), __FILE__, __LINE__);
			return 1;
		}

		return 0;
	}

	/**
	 * STDIN reader
	 */
	size_t reader(char * destination, size_t amount) {
		return fread((void *) destination, sizeof(char), amount, stdin);
	}

	/**
	 * STDOUT writer
	 */
	size_t writer(const char * data, size_t amount) {
		return fwrite((void *) data, sizeof(char), amount, stdout);
	}

	/**
	 * STDERR error
	 */
	void error(const char * data, const char * file, int line) {
		fwrite((void *) data, sizeof(char), strlen(data), stderr);
		fwrite((void *) "\n", sizeof(char), 1, stderr);
	}

	/**
	 * STDOUT flush
	 * @return whether successful
	 */
	bool flush() {
		return (fflush(stdout) == 0);
	}

	void fromEnvVars() {
		char * env = getenv("PATH_TRANSLATED");
		if (!env) { env = getenv("SCRIPT_FILENAME"); }
		if (env) { this->mainfile = std::string(env); }
	}

private:
	std::string argv0;

	const char * instanceType() {
		return "cli";
	}

	const char * executableName() {
		return this->argv0.c_str();
	}

	/**
	 * Process command line arguments.
	 */
	void process_args(int argc, char ** argv) {
		std::string err = "Invalid command line usage.\n";
		err += "Correct usage: ";
		err += v8cgi_usage; /* see the v8cgi_usage definition for the format */

		int index = 0;

		/* see if we have v8 options */
		bool have_v8args = false;
		for (; index < argc; ++index) {
			/* FIXME: if there is a standalone "--" after the name of the script
			 then this breaks.  I can't figure out a solution to this, so
			 for now we don't support any standalone "--" after the script name.
			 One solution (and the way it currently works) is to require "--"
			 before all other args even if no v8 args are used, but that seems
			 I don't like this, but it is where we are right now. */
			if (std::string(argv[index]) == "--") {
				/* treat all previous arguments as v8 arguments */
				int v8argc = index;
				v8::V8::SetFlagsFromCommandLine(&v8argc, argv, true);
				index++; /* skip over the "--" */
				have_v8args = true;
				break;
			}
		}

		/* if there were no v8 args, then reset index to the first argument */
		if (!have_v8args) { index = 1; }

		/* scan for v8cgi-specific arguments now */
		while (index < argc) {
			std::string optname(argv[index]);
			if (optname[0] != '-') { break; } /* not starting with "-" => mainfile */
			if (optname.length() != 2) { throw err; } /* one-character options only */
			index++; /* skip the option name */

			switch (optname[1]) {
				case 'c':
					if (index >= argc) { throw err; } /* missing option value */
					this->cfgfile = argv[index];
#ifdef VERBOSE
					printf("cfgfile: %s\n", argv[index]);
#endif
					index++; /* skip the option value */
				break;

				case 'd':
					if (index >= argc) { throw err; } /* missing option value */
					v8::Debug::EnableAgent("v8cgi", atoi(argv[index]));
#ifdef VERBOSE
					printf("port: %s\n", argv[index]);
#endif
					index++; /* skip the option value */
				break;

				case 'h':
					printf(v8cgi_usage);
					printf("\n");
				break;

				case 'v':
					printf("v8cgi version %s", STRING(VERSION));
					printf("\n");
				break;

				default:
					throw err;
				break;
			}

		}

		if (index < argc) {
			/* argv[index] is the program file */
			this->mainfile = argv[index];
			/* expand mainfile to absolute path */
			if (!path_isabsolute(this->mainfile)) {
				std::string tmp = path_getcwd();
				tmp += "/";
				tmp += this->mainfile;
				this->mainfile = path_normalize(this->mainfile);
			}
			index++; /* skip over the program_file */
		}

		/* all the rest of the arguments are arguments to the program_file */
		for (; index < argc; ++index) {
#ifdef VERBOSE
			printf("program_arg: %s\n", argv[index]);
#endif
			this->mainfile_args.push_back(std::string(argv[index]));
		}
	}
};

#ifdef FASTCGI
	/**
	 * This is true only after we receive a signal to terminate
	 */
	void handle_sigterm(int param) {
		FCGI_SetExitStatus(0);
		exit(0);
 	}

	void handle_sigusr1(int param) {
		FCGI_SetExitStatus(0);
		exit(0);
	}

	void handle_sigpipe(int param) {
		FCGI_SetExitStatus(0);
		exit(0);
	}
#endif

extern char ** environ;

int main(int argc, char ** argv) {
	int result = 0;
	v8cgi_CGI cgi;
	result = cgi.init(argc, argv);
	if (result) { exit(result); }

#ifdef FASTCGI
	signal(SIGTERM, handle_sigterm);
	signal(SIGUSR1, handle_sigusr1);
	signal(SIGPIPE, handle_sigpipe);
	/**
	 * FastCGI main loop
	 */
	while (FCGI_Accept() >= 0) {
		cgi.fromEnvVars();
#endif

		result = cgi.execute(environ);

#ifdef FASTCGI
		FCGI_SetExitStatus(result);
	}
#endif

	return result;
}
<|endoftext|>


<commit_before>/** @file

    Plugin to perform background fetches of certain content that would
    otherwise not be cached. For example, Range: requests / responses.

    @section license License

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you 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 <stdio.h>
#include <ts/ts.h>
#include <openssl/ssl.h>
#include <string>
#include <map>
#include <string.h>

using namespace std;

const char* PLUGIN_NAME = "sni_proto_nego";
const int MAX_BUFFER_SIZE = 1024;
const int MAX_FILE_PATH_SIZE = 1024;
const unsigned int MAX_PROTO_LIST_LEN = 100;
const unsigned int MAX_PROTO_NAME_LEN = 255;

typedef struct {
  bool enableNpn;
  unsigned int npn_proto_list_count;
  unsigned char npn_proto_list [MAX_PROTO_LIST_LEN] [MAX_PROTO_NAME_LEN];
} SNIProtoConfig;

typedef map<string, SNIProtoConfig> stringMap;
static  stringMap _sniProtoMap;

static
bool read_config(char* config_file) {
  char file_path[MAX_FILE_PATH_SIZE];
  TSFile file;
  if (config_file == NULL) {
    TSError("invalid config file");
    return false;
  }
  TSDebug(PLUGIN_NAME, "trying to open config file in this path: %s", file_path);
  file = TSfopen(config_file, "r");
  if (file == NULL) {
    snprintf(file_path, sizeof(file_path), "%s/%s", TSInstallDirGet(), config_file);
    file = TSfopen(file_path, "r");
    if (file == NULL) {
      TSError("Failed to open config file %s", config_file);
      return false;
    }
  }
  char buffer[MAX_BUFFER_SIZE];
  memset(buffer, 0, sizeof(buffer));
  while (TSfgets(file, buffer, sizeof(buffer) - 1) != NULL) {
    char *eol = 0;
    // make sure line was not bigger than buffer
    if ((eol = strchr(buffer, '\n')) == NULL && (eol = strstr(buffer, "\r\n")) == NULL) {
      TSError("sni_proto_nego line too long, did not get a good line in cfg, skipping, line: %s", buffer);
      memset(buffer, 0, sizeof(buffer));
      continue;
    }
    // make sure line has something useful on it
    if (eol - buffer < 2 || buffer[0] == '#') {
      memset(buffer, 0, sizeof(buffer));
      continue;
    }
    char* cfg = strtok(buffer, "\n\r\n");

    if (cfg != NULL) {
        TSDebug(PLUGIN_NAME, "setting SniProto based on string: %s", cfg);

        char* domain = strtok(buffer, " ");
        SNIProtoConfig sniProtoConfig = {1, 1};

        if (domain) {
          if ((*domain == '*') && (domain+1) && (*(domain+1)=='.')) {
            domain += 2;
            if (domain == NULL) {
              continue;
            }
          }
          char* sni_proto_config = strtok (NULL, " ");
          if (sni_proto_config) {
            sniProtoConfig.enableNpn = atoi(sni_proto_config);
            TSDebug(PLUGIN_NAME, "npn_proto_config %d", sniProtoConfig.enableNpn);
            sni_proto_config = strtok (NULL, " ");
            // now get the npn proto advertisment list
            sni_proto_config = strtok (NULL, " ");
            sniProtoConfig.npn_proto_list_count = 0;
            while (sni_proto_config != NULL) {
              char* proto = strtok(NULL, "|");
              if ((proto == NULL) ||
                  (sniProtoConfig.npn_proto_list_count >= MAX_PROTO_LIST_LEN) ||
                  (strlen(proto) >= MAX_PROTO_NAME_LEN)) {
                break;
              }
              _TSstrlcpy((char*)sniProtoConfig.npn_proto_list[sniProtoConfig.npn_proto_list_count++], proto, (strlen(proto) + 1));
            }
          }
          _sniProtoMap.insert(make_pair(domain, sniProtoConfig));
        }

        memset(buffer, 0, sizeof(buffer));
    }
  }

  TSfclose(file);

  TSDebug(PLUGIN_NAME, "Done parsing config");

  return true;
}

static void
init_sni_callback(void *sslNetVC)
{
  TSVConn ssl_vc = reinterpret_cast<TSVConn>(sslNetVC);
  TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc);
  SSL *ssl = reinterpret_cast<SSL *>(sslobj);
  const char *serverName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
  SSL_CTX * ctx = SSL_get_SSL_CTX(ssl);

  if (serverName == NULL) {
    TSDebug(PLUGIN_NAME, "invalid ssl netVC %p, servername %s for ssl obj %p", sslNetVC, serverName, ssl);
    return;
  }

  TSDebug(PLUGIN_NAME, "ssl netVC %p, servername %s for ssl obj %p", sslNetVC, serverName, ssl);

  stringMap::iterator it;
  it=_sniProtoMap.find(serverName);

  // check for wild-card domains
  if(it==_sniProtoMap.end()) {
    char* domain = strstr((char*)serverName, ".");
    if (domain && (domain+1)) {
      it=_sniProtoMap.find(domain+1);
    }
  }

  if (it!=_sniProtoMap.end()) {
    SNIProtoConfig sniProtoConfig = it->second;
    if (!sniProtoConfig.enableNpn) {
      TSDebug(PLUGIN_NAME, "disabling NPN for serverName %s", serverName);
      SSL_CTX_set_next_protos_advertised_cb(ctx, NULL, NULL);
    } else {
      TSDebug(PLUGIN_NAME, "setting NPN advertised list for %s", serverName);
      TSSslAdvertiseProtocolSet(ssl_vc, (const unsigned char **)sniProtoConfig.npn_proto_list, sniProtoConfig.npn_proto_list_count);
    }
  } else {
    TSDebug(PLUGIN_NAME, "setting NPN advertised list for %s", serverName);
    TSSslAdvertiseProtocolSet(ssl_vc, NULL, 0);
  }
}

int
SSLSniInitCallbackHandler(TSCont /* cont */, TSEvent /* id */, void* sslNetVC) {
  init_sni_callback(sslNetVC);
  return TS_EVENT_NONE;
}

void
TSPluginInit(int argc, const char *argv[])
{
  (void) argc;
  TSPluginRegistrationInfo info;

  info.plugin_name = (char *)("sni_proto_nego");
  info.vendor_name = (char *)("ats");

  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
    TSError("Plugin registration failed.");
  }

  char* config_file = (char*)"conf/sni_proto_nego/sni_proto_nego.config";

  if (argc >= 2) {
    config_file = (char*)argv[1];
  }

  if (!read_config(config_file)) {
    TSDebug(PLUGIN_NAME, "nothing to do..");
    return;
  }

  TSCont cont = TSContCreate(SSLSniInitCallbackHandler, NULL);
  TSHttpHookAdd(TS_SSL_SNI_HOOK, cont);
}
<commit_msg>Revert "fix build error"<commit_after>/** @file

    Plugin to perform background fetches of certain content that would
    otherwise not be cached. For example, Range: requests / responses.

    @section license License

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you 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 <stdio.h>
#include <ts/ts.h>
#include <ts/apidefs.h>
#include <openssl/ssl.h>
#include <string>
#include <map>
#include <string.h>

using namespace std;

const char* PLUGIN_NAME = "sni_proto_nego";
const int MAX_BUFFER_SIZE = 1024;
const int MAX_FILE_PATH_SIZE = 1024;
const unsigned int MAX_PROTO_LIST_LEN = 100;
const unsigned int MAX_PROTO_NAME_LEN = 255;

typedef struct {
  bool enableNpn;
  unsigned int npn_proto_list_count;
  unsigned char npn_proto_list [MAX_PROTO_LIST_LEN] [MAX_PROTO_NAME_LEN];
} SNIProtoConfig;

typedef map<string, SNIProtoConfig> stringMap;
static  stringMap _sniProtoMap;

static
bool read_config(char* config_file) {
  char file_path[MAX_FILE_PATH_SIZE];
  TSFile file;
  if (config_file == NULL) {
    TSError("invalid config file");
    return false;
  }
  TSDebug(PLUGIN_NAME, "trying to open config file in this path: %s", file_path);
  file = TSfopen(config_file, "r");
  if (file == NULL) {
    snprintf(file_path, sizeof(file_path), "%s/%s", TSInstallDirGet(), config_file);
    file = TSfopen(file_path, "r");
    if (file == NULL) {
      TSError("Failed to open config file %s", config_file);
      return false;
    }
  }
  char buffer[MAX_BUFFER_SIZE];
  memset(buffer, 0, sizeof(buffer));
  while (TSfgets(file, buffer, sizeof(buffer) - 1) != NULL) {
    char *eol = 0;
    // make sure line was not bigger than buffer
    if ((eol = strchr(buffer, '\n')) == NULL && (eol = strstr(buffer, "\r\n")) == NULL) {
      TSError("sni_proto_nego line too long, did not get a good line in cfg, skipping, line: %s", buffer);
      memset(buffer, 0, sizeof(buffer));
      continue;
    }
    // make sure line has something useful on it
    if (eol - buffer < 2 || buffer[0] == '#') {
      memset(buffer, 0, sizeof(buffer));
      continue;
    }
    char* cfg = strtok(buffer, "\n\r\n");

    if (cfg != NULL) {
        TSDebug(PLUGIN_NAME, "setting SniProto based on string: %s", cfg);

        char* domain = strtok(buffer, " ");
        SNIProtoConfig sniProtoConfig = {1, 1};

        if (domain) {
          if ((*domain == '*') && (domain+1) && (*(domain+1)=='.')) {
            domain += 2;
            if (domain == NULL) {
              continue;
            }
          }
          char* sni_proto_config = strtok (NULL, " ");
          if (sni_proto_config) {
            sniProtoConfig.enableNpn = atoi(sni_proto_config);
            TSDebug(PLUGIN_NAME, "npn_proto_config %d", sniProtoConfig.enableNpn);
            sni_proto_config = strtok (NULL, " ");
            // now get the npn proto advertisment list
            sni_proto_config = strtok (NULL, " ");
            sniProtoConfig.npn_proto_list_count = 0;
            while (sni_proto_config != NULL) {
              char* proto = strtok(NULL, "|");
              if ((proto == NULL) ||
                  (sniProtoConfig.npn_proto_list_count >= MAX_PROTO_LIST_LEN) ||
                  (strlen(proto) >= MAX_PROTO_NAME_LEN)) {
                break;
              }
              _TSstrlcpy((char*)sniProtoConfig.npn_proto_list[sniProtoConfig.npn_proto_list_count++], proto, (strlen(proto) + 1));
            }
          }
          _sniProtoMap.insert(make_pair(domain, sniProtoConfig));
        }

        memset(buffer, 0, sizeof(buffer));
    }
  }

  TSfclose(file);

  TSDebug(PLUGIN_NAME, "Done parsing config");

  return true;
}

static void
init_sni_callback(void *sslNetVC)
{
  TSVConn ssl_vc = reinterpret_cast<TSVConn>(sslNetVC);
  TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc);
  SSL *ssl = reinterpret_cast<SSL *>(sslobj);
  const char *serverName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
  SSL_CTX * ctx = SSL_get_SSL_CTX(ssl);

  if (serverName == NULL) {
    TSDebug(PLUGIN_NAME, "invalid ssl netVC %p, servername %s for ssl obj %p", sslNetVC, serverName, ssl);
    return;
  }

  TSDebug(PLUGIN_NAME, "ssl netVC %p, servername %s for ssl obj %p", sslNetVC, serverName, ssl);

  stringMap::iterator it;
  it=_sniProtoMap.find(serverName);

  // check for wild-card domains
  if(it==_sniProtoMap.end()) {
    char* domain = strstr((char*)serverName, ".");
    if (domain && (domain+1)) {
      it=_sniProtoMap.find(domain+1);
    }
  }

  if (it!=_sniProtoMap.end()) {
    SNIProtoConfig sniProtoConfig = it->second;
    if (!sniProtoConfig.enableNpn) {
      TSDebug(PLUGIN_NAME, "disabling NPN for serverName %s", serverName);
      SSL_CTX_set_next_protos_advertised_cb(ctx, NULL, NULL);
    } else {
      TSDebug(PLUGIN_NAME, "setting NPN advertised list for %s", serverName);
      TSSslAdvertiseProtocolSet(ssl_vc, (const unsigned char **)sniProtoConfig.npn_proto_list, sniProtoConfig.npn_proto_list_count);
    }
  } else {
    TSDebug(PLUGIN_NAME, "setting NPN advertised list for %s", serverName);
    TSSslAdvertiseProtocolSet(ssl_vc, NULL, 0);
  }
}

int
SSLSniInitCallbackHandler(TSCont cont, TSEvent id, void* sslNetVC) {
  (void) cont;
  TSDebug(PLUGIN_NAME, "SSLSniInitCallbackHandler with id %d", id);
  switch (id) {
  case TS_SSL_SNI_HOOK:
      {
        init_sni_callback(sslNetVC);
      }
      break;

  default:
    TSDebug(PLUGIN_NAME, "Unexpected event %d", id);
    break;
  }

  return TS_EVENT_NONE;
}

void
TSPluginInit(int argc, const char *argv[])
{
  (void) argc;
  TSPluginRegistrationInfo info;

  info.plugin_name = (char *)("sni_proto_nego");
  info.vendor_name = (char *)("ats");

  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
    TSError("Plugin registration failed.");
  }

  char* config_file = (char*)"conf/sni_proto_nego/sni_proto_nego.config";

  if (argc >= 2) {
    config_file = (char*)argv[1];
  }

  if (!read_config(config_file)) {
    TSDebug(PLUGIN_NAME, "nothing to do..");
    return;
  }

  TSCont cont = TSContCreate(SSLSniInitCallbackHandler, NULL);
  TSHttpHookAdd(TS_SSL_SNI_HOOK, cont);
}
<|endoftext|>


<commit_before><commit_msg>helloWorldScene<commit_after><|endoftext|>


<commit_before>#include "controller.hpp"
#include "element.hpp"

#include "../map/drawer_yg.hpp"

#include "../yg/overlay.hpp"

#include "../std/bind.hpp"

namespace gui
{
  Controller::RenderParams::RenderParams()
    : m_VisualScale(0), m_GlyphCache(0)
  {}

  Controller::Controller()
    : m_VisualScale(0), m_GlyphCache(0)
  {}

  Controller::RenderParams::RenderParams(double visualScale,
                                         TInvalidateFn invalidateFn,
                                         yg::GlyphCache * glyphCache,
                                         yg::gl::Screen * cacheScreen)
    : m_VisualScale(visualScale),
      m_InvalidateFn(invalidateFn),
      m_GlyphCache(glyphCache),
      m_CacheScreen(cacheScreen)
  {}

  Controller::~Controller()
  {}

  void Controller::SelectElements(m2::PointD const & pt, elem_list_t & l, bool onlyVisible)
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
    {
      shared_ptr<gui::Element> const & e = *it;
      if ((!onlyVisible || e->isVisible()) && e->roughHitTest(pt) && e->hitTest(pt))
        l.push_back(e);
    }
  }

  bool Controller::OnTapStarted(m2::PointD const & pt)
  {
    elem_list_t l;

    SelectElements(pt, l, true);

    /// selecting first hit-tested element from the list
    if (!l.empty())
    {
      m_focusedElement = l.front();
      m_focusedElement->onTapStarted(pt);
      return true;
    }

    return false;
  }

  bool Controller::OnTapMoved(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      if (!m_focusedElement->roughHitTest(pt) || !m_focusedElement->hitTest(pt))
        m_focusedElement->onTapCancelled(pt);
      else
        m_focusedElement->onTapMoved(pt);

      /// event handled
      return true;
    }

    return false;
  }

  bool Controller::OnTapEnded(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      m_focusedElement->onTapEnded(pt);
      m_focusedElement.reset();

      return true;
    }

    return false;
  }

  bool Controller::OnTapCancelled(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      m_focusedElement->onTapCancelled(pt);
      m_focusedElement.reset();
      return true;
    }

    return false;
  }

  void Controller::RemoveElement(shared_ptr<Element> const & e)
  {
    elem_list_t::iterator it = find(m_Elements.begin(), m_Elements.end(), e);

    if (it != m_Elements.end())
      m_Elements.erase(it);

    e->setController(0);
  }

  void Controller::AddElement(shared_ptr<Element> const & e)
  {
    e->setController(this);
    m_Elements.push_back(e);
  }

  double Controller::GetVisualScale() const
  {
    return m_VisualScale;
  }

  void Controller::SetRenderParams(RenderParams const & p)
  {
    m_GlyphCache = p.m_GlyphCache;
    m_InvalidateFn = p.m_InvalidateFn;
    m_VisualScale = p.m_VisualScale;
    m_CacheScreen = p.m_CacheScreen;
  }

  void Controller::ResetRenderParams()
  {
    m_GlyphCache = 0;
    m_VisualScale = 0;
    m_InvalidateFn.clear();
    m_CacheScreen = 0;

    PurgeElements();
  }

  void Controller::DrawFrame(yg::gl::Screen * screen)
  {
    screen->beginFrame();

    math::Matrix<double, 3, 3> m = math::Identity<double, 3>();

    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
      (*it)->draw(screen, m);

    screen->endFrame();
  }

  void Controller::Invalidate()
  {
    if (m_InvalidateFn)
      m_InvalidateFn();
  }

  yg::GlyphCache * Controller::GetGlyphCache() const
  {
    return m_GlyphCache;
  }

  void Controller::SetStringsBundle(StringsBundle const * bundle)
  {
    m_bundle = bundle;

    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
    {
      (*it)->setIsDirtyRect(true);
      (*it)->setIsDirtyDrawing(true);
    }
  }

  StringsBundle const * Controller::GetStringsBundle() const
  {
    return m_bundle;
  }

  yg::gl::Screen * Controller::GetCacheScreen() const
  {
    return m_CacheScreen;
  }

  void Controller::UpdateElements()
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
      (*it)->update();
  }

  void Controller::PurgeElements()
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
      (*it)->purge();
  }
}
<commit_msg>invalidating GUI element upon purging.<commit_after>#include "controller.hpp"
#include "element.hpp"

#include "../map/drawer_yg.hpp"

#include "../yg/overlay.hpp"

#include "../std/bind.hpp"

namespace gui
{
  Controller::RenderParams::RenderParams()
    : m_VisualScale(0), m_GlyphCache(0)
  {}

  Controller::Controller()
    : m_VisualScale(0), m_GlyphCache(0)
  {}

  Controller::RenderParams::RenderParams(double visualScale,
                                         TInvalidateFn invalidateFn,
                                         yg::GlyphCache * glyphCache,
                                         yg::gl::Screen * cacheScreen)
    : m_VisualScale(visualScale),
      m_InvalidateFn(invalidateFn),
      m_GlyphCache(glyphCache),
      m_CacheScreen(cacheScreen)
  {}

  Controller::~Controller()
  {}

  void Controller::SelectElements(m2::PointD const & pt, elem_list_t & l, bool onlyVisible)
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
    {
      shared_ptr<gui::Element> const & e = *it;
      if ((!onlyVisible || e->isVisible()) && e->roughHitTest(pt) && e->hitTest(pt))
        l.push_back(e);
    }
  }

  bool Controller::OnTapStarted(m2::PointD const & pt)
  {
    elem_list_t l;

    SelectElements(pt, l, true);

    /// selecting first hit-tested element from the list
    if (!l.empty())
    {
      m_focusedElement = l.front();
      m_focusedElement->onTapStarted(pt);
      return true;
    }

    return false;
  }

  bool Controller::OnTapMoved(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      if (!m_focusedElement->roughHitTest(pt) || !m_focusedElement->hitTest(pt))
        m_focusedElement->onTapCancelled(pt);
      else
        m_focusedElement->onTapMoved(pt);

      /// event handled
      return true;
    }

    return false;
  }

  bool Controller::OnTapEnded(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      m_focusedElement->onTapEnded(pt);
      m_focusedElement.reset();

      return true;
    }

    return false;
  }

  bool Controller::OnTapCancelled(m2::PointD const & pt)
  {
    if (m_focusedElement)
    {
      m_focusedElement->onTapCancelled(pt);
      m_focusedElement.reset();
      return true;
    }

    return false;
  }

  void Controller::RemoveElement(shared_ptr<Element> const & e)
  {
    elem_list_t::iterator it = find(m_Elements.begin(), m_Elements.end(), e);

    if (it != m_Elements.end())
      m_Elements.erase(it);

    e->setController(0);
  }

  void Controller::AddElement(shared_ptr<Element> const & e)
  {
    e->setController(this);
    m_Elements.push_back(e);
  }

  double Controller::GetVisualScale() const
  {
    return m_VisualScale;
  }

  void Controller::SetRenderParams(RenderParams const & p)
  {
    m_GlyphCache = p.m_GlyphCache;
    m_InvalidateFn = p.m_InvalidateFn;
    m_VisualScale = p.m_VisualScale;
    m_CacheScreen = p.m_CacheScreen;
  }

  void Controller::ResetRenderParams()
  {
    m_GlyphCache = 0;
    m_VisualScale = 0;
    m_InvalidateFn.clear();
    m_CacheScreen = 0;

    PurgeElements();
  }

  void Controller::DrawFrame(yg::gl::Screen * screen)
  {
    screen->beginFrame();

    math::Matrix<double, 3, 3> m = math::Identity<double, 3>();

    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
      (*it)->draw(screen, m);

    screen->endFrame();
  }

  void Controller::Invalidate()
  {
    if (m_InvalidateFn)
      m_InvalidateFn();
  }

  yg::GlyphCache * Controller::GetGlyphCache() const
  {
    return m_GlyphCache;
  }

  void Controller::SetStringsBundle(StringsBundle const * bundle)
  {
    m_bundle = bundle;

    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
    {
      (*it)->setIsDirtyRect(true);
      (*it)->setIsDirtyDrawing(true);
    }
  }

  StringsBundle const * Controller::GetStringsBundle() const
  {
    return m_bundle;
  }

  yg::gl::Screen * Controller::GetCacheScreen() const
  {
    return m_CacheScreen;
  }

  void Controller::UpdateElements()
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
      (*it)->update();
  }

  void Controller::PurgeElements()
  {
    for (elem_list_t::const_iterator it = m_Elements.begin();
         it != m_Elements.end();
         ++it)
    {
      (*it)->purge();
      (*it)->setIsDirtyDrawing(true);
      (*it)->setIsDirtyRect(true);
    }
  }
}
<|endoftext|>


<commit_before>#include "mainwindow.h"

#include <string>
#include <QRegularExpression>

#include "query_widget.h"
#include "codeview_widget.h"
#include "session.h"

MainWindow::MainWindow() {
	setWindowTitle(tr("CppQuery"));

	QDockWidget *searchResultDock = new QDockWidget(tr("Search Results"), this);
	QDockWidget *queryTextDock = new QDockWidget(tr("Query"), this);

	searchResultDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
	queryTextDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);

	searchResults = new QListWidget(searchResultDock);
	queryWidget = new QueryWidget(queryTextDock);

	searchResultDock->setWidget(searchResults);
	queryTextDock->setWidget(queryWidget);

	addDockWidget(Qt::LeftDockWidgetArea, searchResultDock);
	addDockWidget(Qt::BottomDockWidgetArea, queryTextDock);

	resultText = new CodeViewArea(this);
	setCentralWidget(resultText);
	resultText->setReadOnly(true);
	resultText->setLineWrapMode(QPlainTextEdit::NoWrap);

	createMenuBar();

	statusBar()->showMessage(tr("Ready"));

	connect(queryWidget, &QueryWidget::executeQuery, this, &MainWindow::executeQuery);
	connect(searchResults, &QListWidget::itemDoubleClicked, this, &MainWindow::openResult);
}

MainWindow::~MainWindow() {

}

void MainWindow::createMenuBar() {
	exitAct = new QAction(tr("E&xit"), this);
	aboutAct = new QAction(tr("About"), this);
	aboutQtAct = new QAction(tr("About Qt"), this);

	openAct = new QAction(tr("&Open..."), this);
	openAct->setShortcuts(QKeySequence::Open);
	openAct->setStatusTip(tr("Open a JSON compilation database."));

	exitAct->setShortcuts(QKeySequence::Quit);

	connect(openAct, &QAction::triggered, this, &MainWindow::open);
	connect(exitAct, &QAction::triggered, this, &MainWindow::close);
	connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
	connect(aboutQtAct, &QAction::triggered, this, &QApplication::aboutQt);

	fileMenu = menuBar()->addMenu(tr("&File"));
	helpMenu = menuBar()->addMenu(tr("&Help"));

	fileMenu->addAction(openAct);
	fileMenu->addAction(exitAct);
	helpMenu->addAction(aboutAct);
	helpMenu->addAction(aboutQtAct);
}

void MainWindow::open() {
	std::string fileName = QFileDialog::getOpenFileName(this,
    	tr("Open Compilation Database"), "", tr("JSON files (*.json)")).toStdString();

	// TODO: progressbar

	session = std::unique_ptr<Session>(new Session(fileName));
}

void MainWindow::about() {
    QMessageBox::about(this, tr("About Menu"),
            tr("A query language based on Clang's ASTMatcher library, to provide the programmers with a more efficient way to navigate in huge codebases than simple text searches."));
}

void MainWindow::executeQuery(const std::string& query) {
	if (session) {
		session->runQuery(query);

		searchResults->clear();

		auto matches = session->getMatches();

		for( const std::string& entry : matches ) {
			searchResults->addItem(QString::fromStdString(entry));
		}
	}
}

void MainWindow::openResult(QListWidgetItem* item) {
	QString content = item->text();
	QRegularExpression re{R"((.+) \((.+)\): (\d+),\d+)"};
	QRegularExpressionMatch match = re.match(content);

	QString fileName = match.captured(1);
	QString id = match.captured(2);
	unsigned line = match.captured(3).toUInt();

	QFile file{fileName};

	if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
		assert(false && "Unhandled error");
	}

	QTextStream reader(&file);

	resultText->setPlainText(reader.readAll());

	QTextCursor cursor = resultText->textCursor();
	cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line - 1);
	resultText->setTextCursor(cursor);
}
<commit_msg>Status bar indicates if a query is running.<commit_after>#include "mainwindow.h"

#include <string>
#include <QRegularExpression>

#include "query_widget.h"
#include "codeview_widget.h"
#include "session.h"

MainWindow::MainWindow() {
	setWindowTitle(tr("CppQuery"));

	QDockWidget *searchResultDock = new QDockWidget(tr("Search Results"), this);
	QDockWidget *queryTextDock = new QDockWidget(tr("Query"), this);

	searchResultDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
	queryTextDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);

	searchResults = new QListWidget(searchResultDock);
	queryWidget = new QueryWidget(queryTextDock);

	searchResultDock->setWidget(searchResults);
	queryTextDock->setWidget(queryWidget);

	addDockWidget(Qt::LeftDockWidgetArea, searchResultDock);
	addDockWidget(Qt::BottomDockWidgetArea, queryTextDock);

	resultText = new CodeViewArea(this);
	setCentralWidget(resultText);
	resultText->setReadOnly(true);
	resultText->setLineWrapMode(QPlainTextEdit::NoWrap);

	createMenuBar();

	statusBar()->showMessage(tr("Ready"));

	connect(queryWidget, &QueryWidget::executeQuery, this, &MainWindow::executeQuery);
	connect(searchResults, &QListWidget::itemDoubleClicked, this, &MainWindow::openResult);
}

MainWindow::~MainWindow() {

}

void MainWindow::createMenuBar() {
	exitAct = new QAction(tr("E&xit"), this);
	aboutAct = new QAction(tr("About"), this);
	aboutQtAct = new QAction(tr("About Qt"), this);

	openAct = new QAction(tr("&Open..."), this);
	openAct->setShortcuts(QKeySequence::Open);
	openAct->setStatusTip(tr("Open a JSON compilation database."));

	exitAct->setShortcuts(QKeySequence::Quit);

	connect(openAct, &QAction::triggered, this, &MainWindow::open);
	connect(exitAct, &QAction::triggered, this, &MainWindow::close);
	connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
	connect(aboutQtAct, &QAction::triggered, this, &QApplication::aboutQt);

	fileMenu = menuBar()->addMenu(tr("&File"));
	helpMenu = menuBar()->addMenu(tr("&Help"));

	fileMenu->addAction(openAct);
	fileMenu->addAction(exitAct);
	helpMenu->addAction(aboutAct);
	helpMenu->addAction(aboutQtAct);
}

void MainWindow::open() {
	std::string fileName = QFileDialog::getOpenFileName(this,
    	tr("Open Compilation Database"), "", tr("JSON files (*.json)")).toStdString();

	// TODO: progressbar

	session = std::unique_ptr<Session>(new Session(fileName));
}

void MainWindow::about() {
    QMessageBox::about(this, tr("About Menu"),
            tr("A query language based on Clang's ASTMatcher library, to provide the programmers with a more efficient way to navigate in huge codebases than simple text searches."));
}

void MainWindow::executeQuery(const std::string& query) {
	if (session) {
		statusBar()->showMessage(tr("Querying..."));

		session->runQuery(query);

		searchResults->clear();

		auto matches = session->getMatches();

		for( const std::string& entry : matches ) {
			searchResults->addItem(QString::fromStdString(entry));
		}

		statusBar()->showMessage(tr("Ready"));
	}
}

void MainWindow::openResult(QListWidgetItem* item) {
	QString content = item->text();
	QRegularExpression re{R"((.+) \((.+)\): (\d+),\d+)"};
	QRegularExpressionMatch match = re.match(content);

	QString fileName = match.captured(1);
	QString id = match.captured(2);
	unsigned line = match.captured(3).toUInt();

	QFile file{fileName};

	if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
		assert(false && "Unhandled error");
	}

	QTextStream reader(&file);

	resultText->setPlainText(reader.readAll());

	QTextCursor cursor = resultText->textCursor();
	cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line - 1);
	resultText->setTextCursor(cursor);
}
<|endoftext|>


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

#include "chrome/browser/extensions/extension_sync_data.h"

#include "base/logging.h"
#include "chrome/browser/extensions/app_sync_data.h"
#include "chrome/browser/extensions/extension_service.h"
#include "components/crx_file/id_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_url_handlers.h"
#include "sync/api/sync_data.h"
#include "sync/protocol/extension_specifics.pb.h"
#include "sync/protocol/sync.pb.h"

namespace extensions {

ExtensionSyncData::ExtensionSyncData()
    : uninstalled_(false),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
}

ExtensionSyncData::ExtensionSyncData(const syncer::SyncData& sync_data)
    : uninstalled_(false),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
  PopulateFromSyncData(sync_data);
}

ExtensionSyncData::ExtensionSyncData(const syncer::SyncChange& sync_change)
    : uninstalled_(sync_change.change_type() ==
                   syncer::SyncChange::ACTION_DELETE),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
  PopulateFromSyncData(sync_change.sync_data());
}

ExtensionSyncData::ExtensionSyncData(const Extension& extension,
                                     bool enabled,
                                     bool incognito_enabled,
                                     bool remote_install,
                                     OptionalBoolean all_urls_enabled)
    : id_(extension.id()),
      uninstalled_(false),
      enabled_(enabled),
      incognito_enabled_(incognito_enabled),
      remote_install_(remote_install),
      all_urls_enabled_(all_urls_enabled),
      installed_by_custodian_(extension.was_installed_by_custodian()),
      version_(extension.from_bookmark() ? base::Version("0")
                                         : *extension.version()),
      update_url_(ManifestURL::GetUpdateURL(&extension)),
      name_(extension.non_localized_name()) {
}

ExtensionSyncData::~ExtensionSyncData() {}

syncer::SyncData ExtensionSyncData::GetSyncData() const {
  sync_pb::EntitySpecifics specifics;
  PopulateExtensionSpecifics(specifics.mutable_extension());

  return syncer::SyncData::CreateLocalData(id_, name_, specifics);
}

syncer::SyncChange ExtensionSyncData::GetSyncChange(
    syncer::SyncChange::SyncChangeType change_type) const {
  return syncer::SyncChange(FROM_HERE, change_type, GetSyncData());
}

void ExtensionSyncData::PopulateExtensionSpecifics(
    sync_pb::ExtensionSpecifics* specifics) const {
  DCHECK(crx_file::id_util::IdIsValid(id_));
  specifics->set_id(id_);
  specifics->set_update_url(update_url_.spec());
  specifics->set_version(version_.GetString());
  specifics->set_enabled(enabled_);
  specifics->set_incognito_enabled(incognito_enabled_);
  specifics->set_remote_install(remote_install_);
  if (all_urls_enabled_ != BOOLEAN_UNSET)
    specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE);
  specifics->set_installed_by_custodian(installed_by_custodian_);
  specifics->set_name(name_);
}

void ExtensionSyncData::PopulateFromExtensionSpecifics(
    const sync_pb::ExtensionSpecifics& specifics) {
  if (!crx_file::id_util::IdIsValid(specifics.id())) {
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics.";
  }

  Version specifics_version(specifics.version());
  if (!specifics_version.IsValid())
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics.";

  // The update URL must be either empty or valid.
  GURL specifics_update_url(specifics.update_url());
  if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) {
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics.";
  }

  id_ = specifics.id();
  update_url_ = specifics_update_url;
  version_ = specifics_version;
  enabled_ = specifics.enabled();
  incognito_enabled_ = specifics.incognito_enabled();
  if (specifics.has_all_urls_enabled()) {
    all_urls_enabled_ =
        specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE;
  } else {
    // Set this explicitly (even though it's the default) on the offchance
    // that someone is re-using an ExtensionSyncData object.
    all_urls_enabled_ = BOOLEAN_UNSET;
  }
  remote_install_ = specifics.remote_install();
  installed_by_custodian_ = specifics.installed_by_custodian();
  name_ = specifics.name();
}

void ExtensionSyncData::set_uninstalled(bool uninstalled) {
  uninstalled_ = uninstalled;
}

void ExtensionSyncData::PopulateFromSyncData(
    const syncer::SyncData& sync_data) {
  const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics();

  if (entity_specifics.has_extension()) {
    PopulateFromExtensionSpecifics(entity_specifics.extension());
  } else {
    LOG(FATAL) << "Attempt to sync bad EntitySpecifics.";
  }
}

}  // namespace extensions
<commit_msg>Get more useful LOG(FATAL) messages from ExtensionSyncData to help diagnose crashes.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_sync_data.h"

#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/app_sync_data.h"
#include "chrome/browser/extensions/extension_service.h"
#include "components/crx_file/id_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_url_handlers.h"
#include "sync/api/sync_data.h"
#include "sync/protocol/extension_specifics.pb.h"
#include "sync/protocol/sync.pb.h"

namespace extensions {

namespace {

std::string GetExtensionSpecificsLogMessage(
    const sync_pb::ExtensionSpecifics& specifics) {
  return base::StringPrintf("id: %s\nversion: %s\nupdate_url: %s",
                            specifics.id().c_str(),
                            specifics.version().c_str(),
                            specifics.update_url().c_str());
}

}  // namespace

ExtensionSyncData::ExtensionSyncData()
    : uninstalled_(false),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
}

ExtensionSyncData::ExtensionSyncData(const syncer::SyncData& sync_data)
    : uninstalled_(false),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
  PopulateFromSyncData(sync_data);
}

ExtensionSyncData::ExtensionSyncData(const syncer::SyncChange& sync_change)
    : uninstalled_(sync_change.change_type() ==
                   syncer::SyncChange::ACTION_DELETE),
      enabled_(false),
      incognito_enabled_(false),
      remote_install_(false),
      all_urls_enabled_(BOOLEAN_UNSET),
      installed_by_custodian_(false) {
  PopulateFromSyncData(sync_change.sync_data());
}

ExtensionSyncData::ExtensionSyncData(const Extension& extension,
                                     bool enabled,
                                     bool incognito_enabled,
                                     bool remote_install,
                                     OptionalBoolean all_urls_enabled)
    : id_(extension.id()),
      uninstalled_(false),
      enabled_(enabled),
      incognito_enabled_(incognito_enabled),
      remote_install_(remote_install),
      all_urls_enabled_(all_urls_enabled),
      installed_by_custodian_(extension.was_installed_by_custodian()),
      version_(extension.from_bookmark() ? base::Version("0")
                                         : *extension.version()),
      update_url_(ManifestURL::GetUpdateURL(&extension)),
      name_(extension.non_localized_name()) {
}

ExtensionSyncData::~ExtensionSyncData() {}

syncer::SyncData ExtensionSyncData::GetSyncData() const {
  sync_pb::EntitySpecifics specifics;
  PopulateExtensionSpecifics(specifics.mutable_extension());

  return syncer::SyncData::CreateLocalData(id_, name_, specifics);
}

syncer::SyncChange ExtensionSyncData::GetSyncChange(
    syncer::SyncChange::SyncChangeType change_type) const {
  return syncer::SyncChange(FROM_HERE, change_type, GetSyncData());
}

void ExtensionSyncData::PopulateExtensionSpecifics(
    sync_pb::ExtensionSpecifics* specifics) const {
  DCHECK(crx_file::id_util::IdIsValid(id_));
  specifics->set_id(id_);
  specifics->set_update_url(update_url_.spec());
  specifics->set_version(version_.GetString());
  specifics->set_enabled(enabled_);
  specifics->set_incognito_enabled(incognito_enabled_);
  specifics->set_remote_install(remote_install_);
  if (all_urls_enabled_ != BOOLEAN_UNSET)
    specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE);
  specifics->set_installed_by_custodian(installed_by_custodian_);
  specifics->set_name(name_);
}

void ExtensionSyncData::PopulateFromExtensionSpecifics(
    const sync_pb::ExtensionSpecifics& specifics) {
  if (!crx_file::id_util::IdIsValid(specifics.id())) {
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n"
               << GetExtensionSpecificsLogMessage(specifics);
  }

  Version specifics_version(specifics.version());
  if (!specifics_version.IsValid()) {
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad version):\n"
               << GetExtensionSpecificsLogMessage(specifics);
  }

  // The update URL must be either empty or valid.
  GURL specifics_update_url(specifics.update_url());
  if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) {
    LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n"
               << GetExtensionSpecificsLogMessage(specifics);
  }

  id_ = specifics.id();
  update_url_ = specifics_update_url;
  version_ = specifics_version;
  enabled_ = specifics.enabled();
  incognito_enabled_ = specifics.incognito_enabled();
  if (specifics.has_all_urls_enabled()) {
    all_urls_enabled_ =
        specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE;
  } else {
    // Set this explicitly (even though it's the default) on the offchance
    // that someone is re-using an ExtensionSyncData object.
    all_urls_enabled_ = BOOLEAN_UNSET;
  }
  remote_install_ = specifics.remote_install();
  installed_by_custodian_ = specifics.installed_by_custodian();
  name_ = specifics.name();
}

void ExtensionSyncData::set_uninstalled(bool uninstalled) {
  uninstalled_ = uninstalled;
}

void ExtensionSyncData::PopulateFromSyncData(
    const syncer::SyncData& sync_data) {
  const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics();

  if (entity_specifics.has_extension()) {
    PopulateFromExtensionSpecifics(entity_specifics.extension());
  } else {
    LOG(FATAL) << "Attempt to sync bad EntitySpecifics.";
  }
}

}  // namespace extensions
<|endoftext|>


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

#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

class ExperimentalApiTest : public ExtensionApiTest {
public:
  void SetUpCommandLine(CommandLine* command_line) {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PermissionsFail) {
  ASSERT_TRUE(RunExtensionTest("permissions/disabled")) << message_;

  // Since the experimental APIs require a flag, this will fail even though
  // It's enabled.
  // TODO(erikkay) This test is currently broken because LoadExtension in
  // ExtensionBrowserTest doesn't actually fail, it just times out.  To fix this
  // I'll need to add an EXTENSION_LOAD_ERROR notification, which is probably
  // too much for the branch.  I'll enable this on trunk later.
  //ASSERT_FALSE(RunExtensionTest("permissions/enabled"))) << message_;
}

IN_PROC_BROWSER_TEST_F(ExperimentalApiTest, PermissionsSucceed) {
  ASSERT_TRUE(RunExtensionTest("permissions/enabled")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExperimentalPermissionsFail) {
  // At the time this test is being created, there is no experimental
  // function that will not be graduating soon, and does not require a
  // tab id as an argument.  So, we need the tab permission to get
  // a tab id.
  ASSERT_TRUE(RunExtensionTest("permissions/experimental_disabled"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FavIconPermission) {
  ASSERT_TRUE(RunExtensionTest("permissions/favicon")) << message_;
}

// Test functions and APIs that are always allowed (even if you ask for no
// permissions.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AlwaysAllowed) {
  ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_;
}

// TODO(gregoryd): run the NaCl test on all systems once
// http://code.google.com/p/chromium/issues/detail?id=51335 is fixed.
// Meanwhile we run it on Mac OSX only, since we can be sure that an x86-32 NaCl
// module will work there.
// Mark as Flaky.  http://crbug.com/51861
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FLAKY_NaClPermissionEnabled) {
  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kInternalNaCl);
  ASSERT_TRUE(RunExtensionTest("permissions/nacl_enabled")) << message_;
}
#endif
<commit_msg>Shave 10 seconds off browser_tests. Time is wasted in a permission dialog timeout.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

class ExperimentalApiTest : public ExtensionApiTest {
public:
  void SetUpCommandLine(CommandLine* command_line) {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PermissionsFail) {
  ASSERT_TRUE(RunExtensionTest("permissions/disabled")) << message_;

  // Since the experimental APIs require a flag, this will fail even though
  // It's enabled.
  // TODO(erikkay) This test is currently broken because LoadExtension in
  // ExtensionBrowserTest doesn't actually fail, it just times out.  To fix this
  // I'll need to add an EXTENSION_LOAD_ERROR notification, which is probably
  // too much for the branch.  I'll enable this on trunk later.
  //ASSERT_FALSE(RunExtensionTest("permissions/enabled"))) << message_;
}

IN_PROC_BROWSER_TEST_F(ExperimentalApiTest, PermissionsSucceed) {
  ASSERT_TRUE(RunExtensionTest("permissions/enabled")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExperimentalPermissionsFail) {
  // At the time this test is being created, there is no experimental
  // function that will not be graduating soon, and does not require a
  // tab id as an argument.  So, we need the tab permission to get
  // a tab id.
  ASSERT_TRUE(RunExtensionTest("permissions/experimental_disabled"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FavIconPermission) {
  ASSERT_TRUE(RunExtensionTest("permissions/favicon")) << message_;
}

// Test functions and APIs that are always allowed (even if you ask for no
// permissions.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AlwaysAllowed) {
  ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_;
}

// TODO(gregoryd): run the NaCl test on all systems once
// http://code.google.com/p/chromium/issues/detail?id=51335 is fixed.
// Meanwhile we run it on Mac OSX only, since we can be sure that an x86-32 NaCl
// module will work there.
// Mark as Flaky.  http://crbug.com/51861
//
// FLAKY --> DISABLED since it takes 10sec to timeout a dialog.  Need
// faster timeout.
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_NaClPermissionEnabled) {
  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kInternalNaCl);
  ASSERT_TRUE(RunExtensionTest("permissions/nacl_enabled")) << message_;
}
#endif
<|endoftext|>


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

#include "chrome/browser/pepper_broker_infobar_delegate.h"

#include "base/prefs/pref_service.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/plugins/plugin_finder.h"
#include "chrome/browser/plugins/plugin_metadata.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "content/public/common/webplugininfo.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"

#if defined(GOOGLE_TV)
#include "base/android/context_types.h"
#endif

// static
void PepperBrokerInfoBarDelegate::Create(
    content::WebContents* web_contents,
    const GURL& url,
    const base::FilePath& plugin_path,
    const base::Callback<void(bool)>& callback) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  // TODO(wad): Add ephemeral device ID support for broker in guest mode.
  if (profile->IsGuestSession()) {
    callback.Run(false);
    return;
  }

  TabSpecificContentSettings* tab_content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents);

#if defined(OS_CHROMEOS)
  // On ChromeOS, we're ok with granting broker access to the Netflix and
  // Widevine plugins, since they can only come installed with the OS.
  const char kNetflixPluginFileName[] = "libnetflixplugin2.so";
  const char kWidevinePluginFileName[] = "libwidevinecdmadapter.so";
  base::FilePath plugin_file_name = plugin_path.BaseName();
  if (plugin_file_name.value() == FILE_PATH_LITERAL(kNetflixPluginFileName) ||
      plugin_file_name.value() == FILE_PATH_LITERAL(kWidevinePluginFileName)) {
    tab_content_settings->SetPepperBrokerAllowed(true);
    callback.Run(true);
    return;
  }
#endif

#if defined(GOOGLE_TV)
  // On GoogleTV, Netflix crypto/mdx plugin and DRM server adapter plugin can
  // only come pre-installed with the OS, so we're willing to auto-grant access
  // to them. PluginRootName should be matched with PEPPER_PLUGIN_ROOT
  // in PepperPluginManager.java.
  const char kPluginRootName[] = "/system/lib/pepperplugin";
  const char kNetflixCryptoPluginFileName[] = "libnrddpicrypto.so";
  const char kNetflixMdxPluginFileName[] = "libnrdmdx.so";
  const char kDrmServerAdapterPluginFileName[] = "libdrmserveradapter.so";
  base::FilePath::StringType plugin_dir_name = plugin_path.DirName().value();
  base::FilePath::StringType plugin_file_name = plugin_path.BaseName().value();
  if (base::android::IsRunningInWebapp() &&
      plugin_dir_name == FILE_PATH_LITERAL(kPluginRootName) &&
      (plugin_file_name == FILE_PATH_LITERAL(kNetflixCryptoPluginFileName) ||
       plugin_file_name == FILE_PATH_LITERAL(kNetflixMdxPluginFileName) ||
       plugin_file_name ==
          FILE_PATH_LITERAL(kDrmServerAdapterPluginFileName))) {
    tab_content_settings->SetPepperBrokerAllowed(true);
    callback.Run(true);
    return;
  }
#endif

  HostContentSettingsMap* content_settings =
      profile->GetHostContentSettingsMap();
  ContentSetting setting =
      content_settings->GetContentSetting(url, url,
                                          CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
                                          std::string());

  if (setting == CONTENT_SETTING_ASK) {
    content::RecordAction(
        content::UserMetricsAction("PPAPI.BrokerInfobarDisplayed"));
    InfoBarService* infobar_service =
        InfoBarService::FromWebContents(web_contents);
    infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
        new PepperBrokerInfoBarDelegate(
            infobar_service, url, plugin_path,
            profile->GetPrefs()->GetString(prefs::kAcceptLanguages),
            content_settings, tab_content_settings, callback)));
    return;
  }

  bool allowed = (setting == CONTENT_SETTING_ALLOW);
  content::RecordAction(allowed ?
      content::UserMetricsAction("PPAPI.BrokerSettingAllow") :
      content::UserMetricsAction("PPAPI.BrokerSettingDeny"));
  tab_content_settings->SetPepperBrokerAllowed(allowed);
  callback.Run(allowed);
}

PepperBrokerInfoBarDelegate::PepperBrokerInfoBarDelegate(
    InfoBarService* infobar_service,
    const GURL& url,
    const base::FilePath& plugin_path,
    const std::string& languages,
    HostContentSettingsMap* content_settings,
    TabSpecificContentSettings* tab_content_settings,
    const base::Callback<void(bool)>& callback)
    : ConfirmInfoBarDelegate(infobar_service),
      url_(url),
      plugin_path_(plugin_path),
      languages_(languages),
      content_settings_(content_settings),
      tab_content_settings_(tab_content_settings),
      callback_(callback) {
}

PepperBrokerInfoBarDelegate::~PepperBrokerInfoBarDelegate() {
  if (!callback_.is_null())
    callback_.Run(false);
}

int PepperBrokerInfoBarDelegate::GetIconID() const {
  return IDR_INFOBAR_PLUGIN_INSTALL;
}

string16 PepperBrokerInfoBarDelegate::GetMessageText() const {
  content::PluginService* plugin_service =
      content::PluginService::GetInstance();
  content::WebPluginInfo plugin;
  bool success = plugin_service->GetPluginInfoByPath(plugin_path_, &plugin);
  DCHECK(success);
  scoped_ptr<PluginMetadata> plugin_metadata(
      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
  return l10n_util::GetStringFUTF16(IDS_PEPPER_BROKER_MESSAGE,
                                    plugin_metadata->name(),
                                    net::FormatUrl(url_.GetOrigin(),
                                                   languages_));
}

string16 PepperBrokerInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_PEPPER_BROKER_ALLOW_BUTTON : IDS_PEPPER_BROKER_DENY_BUTTON);
}

bool PepperBrokerInfoBarDelegate::Accept() {
  DispatchCallback(true);
  return true;
}

bool PepperBrokerInfoBarDelegate::Cancel() {
  DispatchCallback(false);
  return true;
}

string16 PepperBrokerInfoBarDelegate::GetLinkText() const {
  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
}

bool PepperBrokerInfoBarDelegate::LinkClicked(
    WindowOpenDisposition disposition) {
  GURL learn_more_url("https://support.google.com/chrome/?p=ib_pepper_broker");
  web_contents()->OpenURL(content::OpenURLParams(
      learn_more_url, content::Referrer(),
      (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
      content::PAGE_TRANSITION_LINK, false));
  return false;
}

void PepperBrokerInfoBarDelegate::DispatchCallback(bool result) {
  content::RecordAction(result ?
      content::UserMetricsAction("PPAPI.BrokerInfobarClickedAllow") :
      content::UserMetricsAction("PPAPI.BrokerInfobarClickedDeny"));
  callback_.Run(result);
  callback_ = base::Callback<void(bool)>();
  content_settings_->SetContentSetting(
      ContentSettingsPattern::FromURLNoWildcard(url_),
      ContentSettingsPattern::Wildcard(),
      CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
      std::string(), result ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
  tab_content_settings_->SetPepperBrokerAllowed(result);
}
<commit_msg>Removed old Netflix plugin from the broker whitelist. Added domain check as well.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/pepper_broker_infobar_delegate.h"

#include "base/prefs/pref_service.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/plugins/plugin_finder.h"
#include "chrome/browser/plugins/plugin_metadata.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "content/public/common/webplugininfo.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"

#if defined(GOOGLE_TV)
#include "base/android/context_types.h"
#endif

// static
void PepperBrokerInfoBarDelegate::Create(
    content::WebContents* web_contents,
    const GURL& url,
    const base::FilePath& plugin_path,
    const base::Callback<void(bool)>& callback) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  // TODO(wad): Add ephemeral device ID support for broker in guest mode.
  if (profile->IsGuestSession()) {
    callback.Run(false);
    return;
  }

  TabSpecificContentSettings* tab_content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents);

#if defined(OS_CHROMEOS)
  // On ChromeOS, we're ok with granting broker access to the Netflix and
  // Widevine plugins, since they can only come installed with the OS.
  const char kWidevinePluginFileName[] = "libwidevinecdmadapter.so";
  const char kNetflixDomain[] = "netflix.com";

  base::FilePath plugin_file_name = plugin_path.BaseName();
  if (plugin_file_name.value() == FILE_PATH_LITERAL(kWidevinePluginFileName) &&
      url.DomainIs(kNetflixDomain)) {
    tab_content_settings->SetPepperBrokerAllowed(true);
    callback.Run(true);
    return;
  }
#endif

#if defined(GOOGLE_TV)
  // On GoogleTV, Netflix crypto/mdx plugin and DRM server adapter plugin can
  // only come pre-installed with the OS, so we're willing to auto-grant access
  // to them. PluginRootName should be matched with PEPPER_PLUGIN_ROOT
  // in PepperPluginManager.java.
  const char kPluginRootName[] = "/system/lib/pepperplugin";
  const char kNetflixCryptoPluginFileName[] = "libnrddpicrypto.so";
  const char kNetflixMdxPluginFileName[] = "libnrdmdx.so";
  const char kDrmServerAdapterPluginFileName[] = "libdrmserveradapter.so";
  base::FilePath::StringType plugin_dir_name = plugin_path.DirName().value();
  base::FilePath::StringType plugin_file_name = plugin_path.BaseName().value();
  if (base::android::IsRunningInWebapp() &&
      plugin_dir_name == FILE_PATH_LITERAL(kPluginRootName) &&
      (plugin_file_name == FILE_PATH_LITERAL(kNetflixCryptoPluginFileName) ||
       plugin_file_name == FILE_PATH_LITERAL(kNetflixMdxPluginFileName) ||
       plugin_file_name ==
          FILE_PATH_LITERAL(kDrmServerAdapterPluginFileName))) {
    tab_content_settings->SetPepperBrokerAllowed(true);
    callback.Run(true);
    return;
  }
#endif

  HostContentSettingsMap* content_settings =
      profile->GetHostContentSettingsMap();
  ContentSetting setting =
      content_settings->GetContentSetting(url, url,
                                          CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
                                          std::string());

  if (setting == CONTENT_SETTING_ASK) {
    content::RecordAction(
        content::UserMetricsAction("PPAPI.BrokerInfobarDisplayed"));
    InfoBarService* infobar_service =
        InfoBarService::FromWebContents(web_contents);
    infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
        new PepperBrokerInfoBarDelegate(
            infobar_service, url, plugin_path,
            profile->GetPrefs()->GetString(prefs::kAcceptLanguages),
            content_settings, tab_content_settings, callback)));
    return;
  }

  bool allowed = (setting == CONTENT_SETTING_ALLOW);
  content::RecordAction(allowed ?
      content::UserMetricsAction("PPAPI.BrokerSettingAllow") :
      content::UserMetricsAction("PPAPI.BrokerSettingDeny"));
  tab_content_settings->SetPepperBrokerAllowed(allowed);
  callback.Run(allowed);
}

PepperBrokerInfoBarDelegate::PepperBrokerInfoBarDelegate(
    InfoBarService* infobar_service,
    const GURL& url,
    const base::FilePath& plugin_path,
    const std::string& languages,
    HostContentSettingsMap* content_settings,
    TabSpecificContentSettings* tab_content_settings,
    const base::Callback<void(bool)>& callback)
    : ConfirmInfoBarDelegate(infobar_service),
      url_(url),
      plugin_path_(plugin_path),
      languages_(languages),
      content_settings_(content_settings),
      tab_content_settings_(tab_content_settings),
      callback_(callback) {
}

PepperBrokerInfoBarDelegate::~PepperBrokerInfoBarDelegate() {
  if (!callback_.is_null())
    callback_.Run(false);
}

int PepperBrokerInfoBarDelegate::GetIconID() const {
  return IDR_INFOBAR_PLUGIN_INSTALL;
}

string16 PepperBrokerInfoBarDelegate::GetMessageText() const {
  content::PluginService* plugin_service =
      content::PluginService::GetInstance();
  content::WebPluginInfo plugin;
  bool success = plugin_service->GetPluginInfoByPath(plugin_path_, &plugin);
  DCHECK(success);
  scoped_ptr<PluginMetadata> plugin_metadata(
      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
  return l10n_util::GetStringFUTF16(IDS_PEPPER_BROKER_MESSAGE,
                                    plugin_metadata->name(),
                                    net::FormatUrl(url_.GetOrigin(),
                                                   languages_));
}

string16 PepperBrokerInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
      IDS_PEPPER_BROKER_ALLOW_BUTTON : IDS_PEPPER_BROKER_DENY_BUTTON);
}

bool PepperBrokerInfoBarDelegate::Accept() {
  DispatchCallback(true);
  return true;
}

bool PepperBrokerInfoBarDelegate::Cancel() {
  DispatchCallback(false);
  return true;
}

string16 PepperBrokerInfoBarDelegate::GetLinkText() const {
  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
}

bool PepperBrokerInfoBarDelegate::LinkClicked(
    WindowOpenDisposition disposition) {
  GURL learn_more_url("https://support.google.com/chrome/?p=ib_pepper_broker");
  web_contents()->OpenURL(content::OpenURLParams(
      learn_more_url, content::Referrer(),
      (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
      content::PAGE_TRANSITION_LINK, false));
  return false;
}

void PepperBrokerInfoBarDelegate::DispatchCallback(bool result) {
  content::RecordAction(result ?
      content::UserMetricsAction("PPAPI.BrokerInfobarClickedAllow") :
      content::UserMetricsAction("PPAPI.BrokerInfobarClickedDeny"));
  callback_.Run(result);
  callback_ = base::Callback<void(bool)>();
  content_settings_->SetContentSetting(
      ContentSettingsPattern::FromURLNoWildcard(url_),
      ContentSettingsPattern::Wildcard(),
      CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
      std::string(), result ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
  tab_content_settings_->SetPepperBrokerAllowed(result);
}
<|endoftext|>