<commit_before>#ifndef _INCLUDED_RE_PAIR_COMPRESSOR_HPP_
#define _INCLUDED_RE_PAIR_COMPRESSOR_HPP_

#include <tudocomp/Compressor.hpp>

#include <tudocomp/Range.hpp>
#include <tudocomp/coders/BitOptimalCoder.hpp> //default

#include <tudocomp/util/Counter.hpp>

namespace tdc {

template <typename coder_t>
class RePairCompressor : public Compressor {
private:
    typedef uint32_t sym_t;
    typedef uint64_t digram_t;
    typedef std::vector<digram_t> grammar_t;
    static const size_t digram_shift = 32UL;
    static const sym_t sigma = 256; //TODO

    inline static digram_t digram(sym_t l, sym_t r) {
        return (digram_t(l) << digram_shift) | digram_t(r);
    }

    inline static sym_t left(digram_t di) {
        return sym_t(di >> digram_shift);
    }

    inline static sym_t right(digram_t di) {
        return sym_t(di);
    }

    template<typename text_t>
    class Literals {
    private:
        const text_t* m_text;
        len_t         m_text_size;
        const len_t*  m_next;
        len_t         m_pos;

    public:
        inline Literals(const text_t& text, len_t text_size, const len_t* next)
            : m_text(&text), m_text_size(text_size), m_next(next), m_pos(0) {
        }

        inline bool has_next() const {
            return m_pos < m_text_size;
        }

        inline Literal next() {
            assert(has_next());

            auto l = Literal { uliteral_t((*m_text)[m_pos]), m_pos };
            m_pos = m_next[m_pos];
            return l;
        }
    };

public:
    inline static Meta meta() {
        Meta m("compressor", "repair", "Re-Pair compression");
        m.option("coder").templated<coder_t, BitOptimalCoder>();
        m.option("max_rules").dynamic("0");
        return m;
    }

    inline RePairCompressor(Env&& env) : Compressor(std::move(env)) {}

    virtual void compress(Input& input, Output& output) override {
        // options
        size_t max_rules = env().option("max_rules").as_integer();
        if(max_rules == 0) max_rules = SIZE_MAX;

        // prepare editable text
        len_t n;
        sym_t *text;
        len_t *next; //TODO use an int vector of required bit width

        {
            auto view = input.as_view();
            n = view.size();
            text = new sym_t[n];
            next = new len_t[n];

            for(size_t i = 0; i < n; i++) {
                text[i] = view[i];
                next[i] = i + 1;
            }
        }

        // compute RePair grammar
        grammar_t grammar;

        size_t num_replaced = 0;

        do {
            // count digrams
            digram_t max;
            size_t max_count = 0;

            {
                std::unordered_map<digram_t, size_t> count;
                // TODO: probably not optimal, but twice as fast as std::map

                size_t i = 0;
                while(i < n - 1) {
                    size_t j = next[i];
                    if(j >= n) break; // break if at end

                    digram_t di = digram(text[i], text[j]);

                    // update counter
                    size_t c = count[di] + 1;
                    count[di] = c;

                    // update max
                    if(c > max_count) {
                        max = di;
                        max_count = c;
                    }

                    // advance
                    i = j;
                }
            }

            // replace most common digram (max)
            if(max_count > 1) {
                sym_t new_sym = sigma + grammar.size();
                grammar.push_back(max);

                size_t i = 0;
                while(i < n - 1) {
                    size_t j = next[i];
                    if(j >= n) break; // break if at end

                    digram_t di = digram(text[i], text[j]);
                    if(di == max) {
                        text[i] = new_sym; // replace symbol at i by new symbol
                        next[i] = next[j];

                        ++num_replaced;
                    }

                    // advance
                    i = next[i];
                }
            } else {
                break; // done
            }
        } while(grammar.size() < max_rules);

        // debug
        /*
        {
            DLOG(INFO) << "grammar:";
            for(size_t i = 0; i < grammar.size(); i++) {
                digram_t di = grammar[i];
                sym_t l = left(di);
                sym_t r = right(di);

                DLOG(INFO) << uint8_t('A' + i) << " -> " <<
                    uint8_t((l < sigma) ? l : ('A' + l - sigma)) <<
                    uint8_t((r < sigma) ? r : ('A' + r - sigma));
            }

            std::ostringstream start;
            for(size_t i = 0; i < n; i = next[i]) {
                sym_t x = text[i];
                start << uint8_t((x < sigma) ? x : ('A' + x - sigma));
            }

            DLOG(INFO) << "S -> " << start.str();
        }
        */

        env().log_stat("rules", grammar.size());
        env().log_stat("replaced", num_replaced);

        // instantiate encoder
        typename coder_t::Encoder coder(env().env_for_option("coder"),
            output, Literals<sym_t*>(text, n, next));

        // encode amount of grammar rules
        coder.encode(grammar.size(), len_r);

        // lambda for encoding symbols
        auto encode_sym = [&](sym_t x, const Range& r) {
            if(x < sigma) {
                coder.encode(false, bit_r);
                coder.encode(x, literal_r);
            } else {
                coder.encode(true, bit_r);
                coder.encode(x - sigma, r);
            }
        };

        // encode grammar rules
        size_t num_grammar_terminals = 0;
        size_t num_grammar_nonterminals = 0;

        for(size_t i = 0; i < grammar.size(); i++) {
            digram_t di = grammar[i];

            Range grammar_r(i);

            // statistics
            sym_t l = left(di);
            if(l < sigma) ++num_grammar_terminals;
            else ++num_grammar_nonterminals;

            sym_t r = right(di);
            if(r < sigma) ++num_grammar_terminals;
            else ++num_grammar_nonterminals;

            encode_sym(l, grammar_r);
            encode_sym(r, grammar_r);
        }

        env().log_stat("grammar_terms", num_grammar_terminals);
        env().log_stat("grammar_nonterms", num_grammar_nonterminals);

        // encode compressed text (start rule)
        size_t num_text_terminals = 0;
        size_t num_text_nonterminals = 0;

        Range grammar_r(grammar.size());
        for(size_t i = 0; i < n; i = next[i]) {
            sym_t x = text[i];

            // statistics
            if(x < sigma) ++num_text_terminals;
            else ++num_text_nonterminals;

            encode_sym(text[i], grammar_r);
        }

        env().log_stat("text_terms", num_text_terminals);
        env().log_stat("text_nonterms", num_text_nonterminals);

        // clean up
        delete[] next;
        delete[] text;
    }

private:
    inline static void decode(sym_t x, const grammar_t& grammar, std::ostream& ostream) {
        if(x < sigma) {
            // terminal
            ostream << uliteral_t(x);
        } else {
            // non-terminal
            digram_t di = grammar[x - sigma];
            decode(left(di),  grammar, ostream);
            decode(right(di), grammar, ostream);
        }
    }

public:
    virtual void decompress(Input& input, Output& output) override {
        // instantiate decoder
        typename coder_t::Decoder decoder(env().env_for_option("coder"), input);

        // lambda for decoding symbols
        auto decode_sym = [&](const Range& r) {
            bool is_nonterminal = decoder.template decode<bool>(bit_r);
            if(is_nonterminal) {
                return sigma + decoder.template decode<sym_t>(r);
            } else {
                return decoder.template decode<sym_t>(literal_r);
            }
        };

        // decode grammar
        grammar_t grammar;
        {
            auto num_rules = decoder.template decode<size_t>(len_r);
            while(num_rules--) {
                Range grammar_r(grammar.size());
                sym_t l = decode_sym(grammar_r);
                sym_t r = decode_sym(grammar_r);
                grammar.push_back(digram(l, r));
            }
        }

        // debug
        /*{
            DLOG(INFO) << "decoded grammar:";
            for(size_t i = 0; i < grammar.size(); i++) {
                digram_t di = grammar[i];
                sym_t l = left(di);
                sym_t r = right(di);

                DLOG(INFO) << uint8_t('A' + i) << " -> " <<
                    uint8_t((l < sigma) ? l : ('A' + l - sigma)) <<
                    uint8_t((r < sigma) ? r : ('A' + r - sigma));
            }
        }*/

        // decode text
        Range grammar_r(grammar.size());

        auto ostream = output.as_stream();
        while(!decoder.eof()) {
            decode(decode_sym(grammar_r), grammar, ostream);
        }
    }
};

}

#endif<commit_msg>Fix RePair literator for Huffman<commit_after>#ifndef _INCLUDED_RE_PAIR_COMPRESSOR_HPP_
#define _INCLUDED_RE_PAIR_COMPRESSOR_HPP_

#include <tudocomp/Compressor.hpp>

#include <tudocomp/Range.hpp>
#include <tudocomp/coders/BitOptimalCoder.hpp> //default

#include <tudocomp/util/Counter.hpp>

namespace tdc {

template <typename coder_t>
class RePairCompressor : public Compressor {
private:
    typedef uint32_t sym_t;
    typedef uint64_t digram_t;
    typedef std::vector<digram_t> grammar_t;
    static const size_t digram_shift = 32UL;
    static const sym_t sigma = 256; //TODO

    inline static digram_t digram(sym_t l, sym_t r) {
        return (digram_t(l) << digram_shift) | digram_t(r);
    }

    inline static sym_t left(digram_t di) {
        return sym_t(di >> digram_shift);
    }

    inline static sym_t right(digram_t di) {
        return sym_t(di);
    }

    template<typename text_t>
    class Literals {
    private:
        const text_t* m_text;
        len_t         m_text_size;
        const len_t*  m_next;
        len_t         m_pos;

        std::vector<uliteral_t> m_g_literals;
        len_t                   m_g_pos;

    public:
        inline Literals(const text_t& text,
                        len_t text_size,
                        const len_t* next,
                        const grammar_t& grammar)
            : m_text(&text), m_text_size(text_size), m_next(next),
              m_pos(0), m_g_pos(0) {

            // count literals from right side of grammar rules
            for(digram_t di : grammar) {
                sym_t l = left(di);
                if(l < sigma) m_g_literals.push_back(uliteral_t(l));

                sym_t r = right(di);
                if(r < sigma) m_g_literals.push_back(uliteral_t(r));
            }
        }

        inline bool has_next() const {
            return m_pos < m_text_size || m_g_pos < m_g_literals.size();
        }

        inline Literal next() {
            assert(has_next());

            if(m_pos < m_text_size) {
                // from encoded text
                auto l = Literal { uliteral_t((*m_text)[m_pos]), m_pos };
                m_pos = m_next[m_pos];
                return l;
            } else {
                // from grammar right sides
                auto l = Literal { m_g_literals[m_g_pos],
                                   m_text_size + 2 * m_g_pos };
                ++m_g_pos;
                return l;
            }
        }
    };

public:
    inline static Meta meta() {
        Meta m("compressor", "repair", "Re-Pair compression");
        m.option("coder").templated<coder_t, BitOptimalCoder>();
        m.option("max_rules").dynamic("0");
        return m;
    }

    inline RePairCompressor(Env&& env) : Compressor(std::move(env)) {}

    virtual void compress(Input& input, Output& output) override {
        // options
        size_t max_rules = env().option("max_rules").as_integer();
        if(max_rules == 0) max_rules = SIZE_MAX;

        // prepare editable text
        len_t n;
        sym_t *text;
        len_t *next; //TODO use an int vector of required bit width

        {
            auto view = input.as_view();
            n = view.size();
            text = new sym_t[n];
            next = new len_t[n];

            for(size_t i = 0; i < n; i++) {
                text[i] = view[i];
                next[i] = i + 1;
            }
        }

        // compute RePair grammar
        grammar_t grammar;

        size_t num_replaced = 0;

        do {
            // count digrams
            digram_t max;
            size_t max_count = 0;

            {
                std::unordered_map<digram_t, size_t> count;
                // TODO: probably not optimal, but twice as fast as std::map

                size_t i = 0;
                while(i < n - 1) {
                    size_t j = next[i];
                    if(j >= n) break; // break if at end

                    digram_t di = digram(text[i], text[j]);

                    // update counter
                    size_t c = count[di] + 1;
                    count[di] = c;

                    // update max
                    if(c > max_count) {
                        max = di;
                        max_count = c;
                    }

                    // advance
                    i = j;
                }
            }

            // replace most common digram (max)
            if(max_count > 1) {
                sym_t new_sym = sigma + grammar.size();
                grammar.push_back(max);

                size_t i = 0;
                while(i < n - 1) {
                    size_t j = next[i];
                    if(j >= n) break; // break if at end

                    digram_t di = digram(text[i], text[j]);
                    if(di == max) {
                        text[i] = new_sym; // replace symbol at i by new symbol
                        next[i] = next[j];

                        ++num_replaced;
                    }

                    // advance
                    i = next[i];
                }
            } else {
                break; // done
            }
        } while(grammar.size() < max_rules);

        // debug
        /*
        {
            DLOG(INFO) << "grammar:";
            for(size_t i = 0; i < grammar.size(); i++) {
                digram_t di = grammar[i];
                sym_t l = left(di);
                sym_t r = right(di);

                DLOG(INFO) << uint8_t('A' + i) << " -> " <<
                    uint8_t((l < sigma) ? l : ('A' + l - sigma)) <<
                    uint8_t((r < sigma) ? r : ('A' + r - sigma));
            }

            std::ostringstream start;
            for(size_t i = 0; i < n; i = next[i]) {
                sym_t x = text[i];
                start << uint8_t((x < sigma) ? x : ('A' + x - sigma));
            }

            DLOG(INFO) << "S -> " << start.str();
        }
        */

        env().log_stat("rules", grammar.size());
        env().log_stat("replaced", num_replaced);

        // instantiate encoder
        typename coder_t::Encoder coder(env().env_for_option("coder"),
            output, Literals<sym_t*>(text, n, next, grammar));

        // encode amount of grammar rules
        coder.encode(grammar.size(), len_r);

        // lambda for encoding symbols
        auto encode_sym = [&](sym_t x, const Range& r) {
            if(x < sigma) {
                coder.encode(false, bit_r);
                coder.encode(x, literal_r);
            } else {
                coder.encode(true, bit_r);
                coder.encode(x - sigma, r);
            }
        };

        // encode grammar rules
        size_t num_grammar_terminals = 0;
        size_t num_grammar_nonterminals = 0;

        for(size_t i = 0; i < grammar.size(); i++) {
            digram_t di = grammar[i];

            Range grammar_r(i);

            // statistics
            sym_t l = left(di);
            if(l < sigma) ++num_grammar_terminals;
            else ++num_grammar_nonterminals;

            sym_t r = right(di);
            if(r < sigma) ++num_grammar_terminals;
            else ++num_grammar_nonterminals;

            encode_sym(l, grammar_r);
            encode_sym(r, grammar_r);
        }

        env().log_stat("grammar_terms", num_grammar_terminals);
        env().log_stat("grammar_nonterms", num_grammar_nonterminals);

        // encode compressed text (start rule)
        size_t num_text_terminals = 0;
        size_t num_text_nonterminals = 0;

        Range grammar_r(grammar.size());
        for(size_t i = 0; i < n; i = next[i]) {
            sym_t x = text[i];

            // statistics
            if(x < sigma) ++num_text_terminals;
            else ++num_text_nonterminals;

            encode_sym(text[i], grammar_r);
        }

        env().log_stat("text_terms", num_text_terminals);
        env().log_stat("text_nonterms", num_text_nonterminals);

        // clean up
        delete[] next;
        delete[] text;
    }

private:
    inline static void decode(sym_t x, const grammar_t& grammar, std::ostream& ostream) {
        if(x < sigma) {
            // terminal
            ostream << uliteral_t(x);
        } else {
            // non-terminal
            digram_t di = grammar[x - sigma];
            decode(left(di),  grammar, ostream);
            decode(right(di), grammar, ostream);
        }
    }

public:
    virtual void decompress(Input& input, Output& output) override {
        // instantiate decoder
        typename coder_t::Decoder decoder(env().env_for_option("coder"), input);

        // lambda for decoding symbols
        auto decode_sym = [&](const Range& r) {
            bool is_nonterminal = decoder.template decode<bool>(bit_r);
            if(is_nonterminal) {
                auto dec = decoder.template decode<sym_t>(r);
                return sigma + dec;
            } else {
                auto dec = sym_t(decoder.template decode<uliteral_t>(literal_r));
                return dec;
            }
        };

        // decode grammar
        grammar_t grammar;
        {
            auto num_rules = decoder.template decode<size_t>(len_r);
            while(num_rules--) {
                Range grammar_r(grammar.size());
                sym_t l = decode_sym(grammar_r);
                sym_t r = decode_sym(grammar_r);
                grammar.push_back(digram(l, r));
            }
        }

        // debug
        /*{
            DLOG(INFO) << "decoded grammar:";
            for(size_t i = 0; i < grammar.size(); i++) {
                digram_t di = grammar[i];
                sym_t l = left(di);
                sym_t r = right(di);

                DLOG(INFO) << uint8_t('A' + i) << " -> " <<
                    uint8_t((l < sigma) ? l : ('A' + l - sigma)) <<
                    uint8_t((r < sigma) ? r : ('A' + r - sigma));
            }
        }*/

        // decode text
        Range grammar_r(grammar.size());

        auto ostream = output.as_stream();
        while(!decoder.eof()) {
            decode(decode_sym(grammar_r), grammar, ostream);
        }
    }
};

}

#endif<|endoftext|>


<commit_before>#include <UtH/UtHEngine.hpp> //UtHEngine main.

#define NEWSCENEFUNC
#include <Scenes.hpp>

// Basic computer main loop.
// Android version is hidden at UtHEngine/android/jni/main.cpp
int main()
{
	uthSceneM.registerNewSceneFunc(NewSceneFunc, COUNT);

	uthEngine.Init();

	uthSceneM.GoToScene(0);  // Remove on finished product!! t. Jani from engine team.

	while (uthEngine.Running())
	{

		uthEngine.Update();
		uthEngine.Draw();
	}

	return 0;
}<commit_msg>skip intro in debug only<commit_after>#include <UtH/UtHEngine.hpp> //UtHEngine main.

#define NEWSCENEFUNC
#include <Scenes.hpp>

// Basic computer main loop.
// Android version is hidden at UtHEngine/android/jni/main.cpp
int main()
{
	uthSceneM.registerNewSceneFunc(NewSceneFunc, COUNT);

	uthEngine.Init();
#if _DEBUG
		uthSceneM.GoToScene(0);
#endif
	while (uthEngine.Running())
	{

		uthEngine.Update();
		uthEngine.Draw();
	}

	return 0;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ColumnLineChartTypeTemplate.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 01:20:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef CHART_COLUMNLINECHARTTYPETEMPLATE_HXX
#define CHART_COLUMNLINECHARTTYPETEMPLATE_HXX

#include "ChartTypeTemplate.hxx"

#include "OPropertySet.hxx"
#include "MutexContainer.hxx"

#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif

#ifndef _COM_SUN_STAR_CHART2_STACKMODE_HPP_
#include <com/sun/star/chart2/StackMode.hpp>
#endif

namespace chart
{

class ColumnLineChartTypeTemplate :
        public helper::MutexContainer,
        public ChartTypeTemplate,
        public ::property::OPropertySet
{
public:
    explicit ColumnLineChartTypeTemplate(
        ::com::sun::star::uno::Reference<
            ::com::sun::star::uno::XComponentContext > const & xContext,
        const ::rtl::OUString & rServiceName,
        ::com::sun::star::chart2::StackMode eStackMode,
        sal_Int32 nNumberOfLines );
    virtual ~ColumnLineChartTypeTemplate();

    /// XServiceInfo declarations
    APPHELPER_XSERVICEINFO_DECL()

    /// merge XInterface implementations
     DECLARE_XINTERFACE()
    /// merge XTypeProvider implementations
     DECLARE_XTYPEPROVIDER()

protected:
    // ____ OPropertySet ____
    virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const
        throw(::com::sun::star::beans::UnknownPropertyException);
    virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper();

    // ____ XPropertySet ____
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL
        getPropertySetInfo()
        throw (::com::sun::star::uno::RuntimeException);

    // ____ XChartTypeTemplate ____
    virtual sal_Bool SAL_CALL matchesTemplate(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram )
        throw (::com::sun::star::uno::RuntimeException);

    // ____ ChartTypeTemplate ____
    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XDataSeriesTreeParent > createDataSeriesTree(
            const ::com::sun::star::uno::Sequence<
                ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XDataSeries > >& aSeriesSeq,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XBoundedCoordinateSystem > & rCoordSys
            );

    virtual ::com::sun::star::chart2::StackMode getYStackMode() const;

    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XChartType > getDefaultChartType()
        throw (::com::sun::star::uno::RuntimeException);

private:
    ::com::sun::star::chart2::StackMode
                       m_eStackMode;
};

} //  namespace chart

// CHART_COLUMNLINECHARTTYPETEMPLATE_HXX
#endif
<commit_msg>INTEGRATION: CWS chart2mst3 (1.5.4); FILE MERGED 2007/03/26 14:15:40 iha 1.5.4.15: #i75590# copy some aspects from old charttype during creation of new 2007/03/01 13:54:30 iha 1.5.4.14: #i71167 & i74564# keep charttype properties if possible when switching charttypes 2005/10/13 17:39:02 iha 1.5.4.13: renamed BoundedCoordinateSystem to CoordinateSystem 2005/10/07 12:03:07 bm 1.5.4.12: RESYNC: (1.5-1.6); FILE MERGED 2005/08/05 14:19:57 bm 1.5.4.11: getStackMode: per chart type (open: percent stacking works per coordinate system, how can this be synched) 2005/07/15 16:07:21 bm 1.5.4.10: keep more old objects on chart type changes 2005/06/27 13:41:57 iha 1.5.4.9: support property number of lines 2004/09/16 12:27:28 bm 1.5.4.8: API simplification 2004/09/15 17:32:05 bm 1.5.4.7: API simplification 2004/05/27 17:27:11 bm 1.5.4.6: +getChartTypeForNewSeries at XChartTypeTemplate 2004/03/24 19:05:24 bm 1.5.4.5: XChartTypeTemplate changed: matchesTemplate may modify the template s properties if bAdaptProperties is true 2004/03/19 14:32:57 bm 1.5.4.4: XDataSource now contains XLabeledDataSources 2004/03/02 16:40:42 bm 1.5.4.3: allow creating more than one coordinate system 2004/02/20 17:43:56 iha 1.5.4.2: integrate categories at ScaleData 2004/02/13 16:51:41 bm 1.5.4.1: join from changes on branch bm_post_chart01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ColumnLineChartTypeTemplate.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-22 18:47:47 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef CHART_COLUMNLINECHARTTYPETEMPLATE_HXX
#define CHART_COLUMNLINECHARTTYPETEMPLATE_HXX

#include "ChartTypeTemplate.hxx"
#include "StackMode.hxx"

#include "OPropertySet.hxx"
#include "MutexContainer.hxx"

#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif

namespace chart
{

class ColumnLineChartTypeTemplate :
        public MutexContainer,
        public ChartTypeTemplate,
        public ::property::OPropertySet
{
public:
    explicit ColumnLineChartTypeTemplate(
        ::com::sun::star::uno::Reference<
            ::com::sun::star::uno::XComponentContext > const & xContext,
        const ::rtl::OUString & rServiceName,
        StackMode eStackMode,
        sal_Int32 nNumberOfLines );
    virtual ~ColumnLineChartTypeTemplate();

    /// XServiceInfo declarations
    APPHELPER_XSERVICEINFO_DECL()

    /// merge XInterface implementations
     DECLARE_XINTERFACE()
    /// merge XTypeProvider implementations
     DECLARE_XTYPEPROVIDER()

protected:
    // ____ OPropertySet ____
    virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const
        throw(::com::sun::star::beans::UnknownPropertyException);
    virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper();

    // ____ XPropertySet ____
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL
        getPropertySetInfo()
        throw (::com::sun::star::uno::RuntimeException);

    // ____ XChartTypeTemplate ____
    virtual sal_Bool SAL_CALL matchesTemplate(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram,
        sal_Bool bAdaptProperties )
        throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType > SAL_CALL
        getChartTypeForNewSeries( const ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType > >& aFormerlyUsedChartTypes )
        throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataInterpreter > SAL_CALL getDataInterpreter()
        throw (::com::sun::star::uno::RuntimeException);

    // ____ ChartTypeTemplate ____
    virtual void createChartTypes(
            const ::com::sun::star::uno::Sequence<
                ::com::sun::star::uno::Sequence<
                    ::com::sun::star::uno::Reference<
                        ::com::sun::star::chart2::XDataSeries > > > & aSeriesSeq,
            const ::com::sun::star::uno::Sequence<
                ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XCoordinateSystem > > & rCoordSys,
            const ::com::sun::star::uno::Sequence<
                  ::com::sun::star::uno::Reference<
                      ::com::sun::star::chart2::XChartType > > & aOldChartTypesSeq
            );

    virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const;

private:
    StackMode          m_eStackMode;
};

} //  namespace chart

// CHART_COLUMNLINECHARTTYPETEMPLATE_HXX
#endif
<|endoftext|>


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

#include <string>

#include "app/l10n_util.h"
#include "base/file_path.h"
#include "base/gfx/rect.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/automation/automation_constants.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"
#include "views/event.h"

class BlockedPopupContainerInteractiveTest : public UITest {
 protected:
  BlockedPopupContainerInteractiveTest() {
    show_window_ = true;
  }

  virtual void SetUp() {
    UITest::SetUp();

    browser_ = automation()->GetBrowserWindow(0);
    ASSERT_TRUE(browser_.get());

    window_ = browser_->GetWindow();
    ASSERT_TRUE(window_.get());

    tab_ = browser_->GetTab(0);
    ASSERT_TRUE(tab_.get());
  }

  void NavigateMainTabTo(const std::wstring& file_name) {
    FilePath filename(test_data_directory_);
    filename = filename.AppendASCII("constrained_files");
    filename = filename.Append(FilePath::FromWStringHack(file_name));
    ASSERT_TRUE(tab_->NavigateToURL(net::FilePathToFileURL(filename)));
  }

  void SimulateClickInCenterOf(const scoped_refptr<WindowProxy>& window) {
    gfx::Rect tab_view_bounds;
    ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                      &tab_view_bounds, true));

    // Simulate a click of the actual link to force user_gesture to be
    // true; if we don't, the resulting popup will be constrained, which
    // isn't what we want to test.
    ASSERT_TRUE(window->SimulateOSClick(tab_view_bounds.CenterPoint(),
                                        views::Event::EF_LEFT_BUTTON_DOWN));
  }

  scoped_refptr<BrowserProxy> browser_;
  scoped_refptr<WindowProxy> window_;
  scoped_refptr<TabProxy> tab_;
};

TEST_F(BlockedPopupContainerInteractiveTest, TestOpenAndResizeTo) {
  NavigateMainTabTo(L"constrained_window_onload_resizeto.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser != NULL);
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window != NULL);

  // Make sure we were created with the correct width and height.
  gfx::Rect rect;
  bool is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);

#if !defined(OS_LINUX)
  // TODO(estade): This is a real failure; we create popups with the wrong size.
  // Fix it. Note: it appears that we are setting the window's bounds to 300,320
  // instead of setting the content's bounds to 300,320.
  EXPECT_EQ(300, rect.width());
  EXPECT_EQ(320, rect.height());
#endif

  SimulateClickInCenterOf(popup_window);

  // No idea how to wait here other then sleeping. This timeout used to be
  // lower, then we started hitting it before it was done. :(
  PlatformThread::Sleep(5000);

  // The actual content will be LESS than (200, 200) because resizeTo
  // deals with a window's outer{Width,Height} instead of its
  // inner{Width,Height}.
  is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                 VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  EXPECT_LT(rect.height(), 200);
#if defined(OS_LINUX)
  // On Linux we may run in an environment where there is no window frame. In
  // this case our width might be exactly 200. The height will still be less
  // because we have to show the location bar.
  EXPECT_LE(rect.width(), 200);
#else
  EXPECT_LT(rect.width(), 200);
#endif
}

// Helper function used to get the number of blocked popups out of the window
// title.
bool ParseCountOutOfTitle(const std::wstring& title, int* output) {
  // Since we will be reading the number of popup windows open by grabbing the
  // number out of the window title, and that format string is localized, we
  // need to find out the offset into that string.
  const wchar_t* placeholder = L"XXXX";
  size_t offset =
      l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, placeholder).
      find(placeholder);

  std::wstring number;
  while (offset < title.size() && iswdigit(title[offset])) {
    number += title[offset];
    offset++;
  }

  return StringToInt(WideToUTF16(number), output);
}

// Tests that in the window.open() equivalent of a fork bomb, we stop building
// windows.
TEST_F(BlockedPopupContainerInteractiveTest, DontSpawnEndlessPopups) {
  NavigateMainTabTo(L"infinite_popups.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

  // And now we spin, waiting to make sure that we don't spawn popup
  // windows endlessly. The current limit is 25, so allowing for possible race
  // conditions and one off errors, don't break out until we go over 30 popup
  // windows (in which case we are bork bork bork).
  const int kMaxPopupWindows = 30;

  int popup_window_count = 0;
  int new_popup_window_count = 0;
  int times_slept = 0;
  bool continuing = true;
  while (continuing && popup_window_count < kMaxPopupWindows) {
    ASSERT_TRUE(popup_tab->GetBlockedPopupCount(&new_popup_window_count));
    if (new_popup_window_count == popup_window_count) {
      if (times_slept == 10) {
        continuing = false;
      } else {
        // Nothing intereseting is going on wait it out.
        PlatformThread::Sleep(automation::kSleepTime);
        times_slept++;
      }
    } else {
      times_slept = 0;
    }

    EXPECT_GE(new_popup_window_count, popup_window_count);
    EXPECT_LE(new_popup_window_count, kMaxPopupWindows);
    popup_window_count = new_popup_window_count;
  }
}

// Make sure that we refuse to close windows when a constrained popup is
// displayed.
TEST_F(BlockedPopupContainerInteractiveTest, WindowOpenWindowClosePopup) {
  NavigateMainTabTo(L"openclose_main.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000));

  // Make sure we have a blocked popup notification
  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());
  ASSERT_TRUE(popup_tab->WaitForBlockedPopupCountToChangeTo(1, 1000));

  // Ensure we didn't close the first popup window.
  ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 3000));
}

TEST_F(BlockedPopupContainerInteractiveTest, BlockAlertFromBlockedPopup) {
  NavigateMainTabTo(L"block_alert.html");

  // Wait for there to be an app modal dialog (and fail if it's shown).
  ASSERT_FALSE(automation()->WaitForAppModalDialog(4000));

  // Ensure one browser window.
  int browser_window_count;
  ASSERT_TRUE(automation()->GetBrowserWindowCount(&browser_window_count));
  ASSERT_EQ(1, browser_window_count);

  // Ensure one blocked popup window: the popup didn't escape.
  int popup_count = 0;
  ASSERT_TRUE(tab_->GetBlockedPopupCount(&popup_count));
  ASSERT_EQ(1, popup_count);
}

TEST_F(BlockedPopupContainerInteractiveTest, ShowAlertFromNormalPopup) {
  NavigateMainTabTo(L"show_alert.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

  SimulateClickInCenterOf(popup_window);

  // Wait for there to be an app modal dialog.
  ASSERT_TRUE(automation()->WaitForAppModalDialog(5000));
}

// Make sure that window focus works while creating a popup window so that we
// don't
TEST_F(BlockedPopupContainerInteractiveTest, DontBreakOnBlur) {
  NavigateMainTabTo(L"window_blur_test.html");
  SimulateClickInCenterOf(window_);

  // Wait for the popup window to open.
  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  // We popup shouldn't be closed by the onblur handler.
  ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 1500));
}
<commit_msg>Fix 2 failing BlockedPopupContainerInteractiveTests on Linux.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "base/file_path.h"
#include "base/gfx/rect.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/automation/automation_constants.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"
#include "views/event.h"

class BlockedPopupContainerInteractiveTest : public UITest {
 protected:
  BlockedPopupContainerInteractiveTest() {
    show_window_ = true;
  }

  virtual void SetUp() {
    UITest::SetUp();

    browser_ = automation()->GetBrowserWindow(0);
    ASSERT_TRUE(browser_.get());

    window_ = browser_->GetWindow();
    ASSERT_TRUE(window_.get());

    tab_ = browser_->GetTab(0);
    ASSERT_TRUE(tab_.get());
  }

  void NavigateMainTabTo(const std::wstring& file_name) {
    FilePath filename(test_data_directory_);
    filename = filename.AppendASCII("constrained_files");
    filename = filename.Append(FilePath::FromWStringHack(file_name));
    ASSERT_TRUE(tab_->NavigateToURL(net::FilePathToFileURL(filename)));
  }

  void SimulateClickInCenterOf(const scoped_refptr<WindowProxy>& window) {
    gfx::Rect tab_view_bounds;
    ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                      &tab_view_bounds, true));

    // Simulate a click of the actual link to force user_gesture to be
    // true; if we don't, the resulting popup will be constrained, which
    // isn't what we want to test.
    ASSERT_TRUE(window->SimulateOSClick(tab_view_bounds.CenterPoint(),
                                        views::Event::EF_LEFT_BUTTON_DOWN));
  }

  scoped_refptr<BrowserProxy> browser_;
  scoped_refptr<WindowProxy> window_;
  scoped_refptr<TabProxy> tab_;
};

TEST_F(BlockedPopupContainerInteractiveTest, TestOpenAndResizeTo) {
  NavigateMainTabTo(L"constrained_window_onload_resizeto.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser != NULL);
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window != NULL);

  // Make sure we were created with the correct width and height.
  gfx::Rect rect;
  bool is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);

#if !defined(OS_LINUX)
  // TODO(estade): This is a real failure; we create popups with the wrong size.
  // Fix it. Note: it appears that we are setting the window's bounds to 300,320
  // instead of setting the content's bounds to 300,320.
  EXPECT_EQ(300, rect.width());
  EXPECT_EQ(320, rect.height());
#endif

#if defined(OS_LINUX)
  // It seems we have to wait a little bit for the widgets to spin up before
  // we can start clicking on them.
  PlatformThread::Sleep(500);
#endif

  SimulateClickInCenterOf(popup_window);

  // No idea how to wait here other then sleeping. This timeout used to be
  // lower, then we started hitting it before it was done. :(
  PlatformThread::Sleep(5000);

  // The actual content will be LESS than (200, 200) because resizeTo
  // deals with a window's outer{Width,Height} instead of its
  // inner{Width,Height}.
  is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                 VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  EXPECT_LT(rect.height(), 200);
#if defined(OS_LINUX)
  // On Linux we may run in an environment where there is no window frame. In
  // this case our width might be exactly 200. The height will still be less
  // because we have to show the location bar.
  EXPECT_LE(rect.width(), 200);
#else
  EXPECT_LT(rect.width(), 200);
#endif
}

// Helper function used to get the number of blocked popups out of the window
// title.
bool ParseCountOutOfTitle(const std::wstring& title, int* output) {
  // Since we will be reading the number of popup windows open by grabbing the
  // number out of the window title, and that format string is localized, we
  // need to find out the offset into that string.
  const wchar_t* placeholder = L"XXXX";
  size_t offset =
      l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, placeholder).
      find(placeholder);

  std::wstring number;
  while (offset < title.size() && iswdigit(title[offset])) {
    number += title[offset];
    offset++;
  }

  return StringToInt(WideToUTF16(number), output);
}

// Tests that in the window.open() equivalent of a fork bomb, we stop building
// windows.
TEST_F(BlockedPopupContainerInteractiveTest, DontSpawnEndlessPopups) {
  NavigateMainTabTo(L"infinite_popups.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

  // And now we spin, waiting to make sure that we don't spawn popup
  // windows endlessly. The current limit is 25, so allowing for possible race
  // conditions and one off errors, don't break out until we go over 30 popup
  // windows (in which case we are bork bork bork).
  const int kMaxPopupWindows = 30;

  int popup_window_count = 0;
  int new_popup_window_count = 0;
  int times_slept = 0;
  bool continuing = true;
  while (continuing && popup_window_count < kMaxPopupWindows) {
    ASSERT_TRUE(popup_tab->GetBlockedPopupCount(&new_popup_window_count));
    if (new_popup_window_count == popup_window_count) {
      if (times_slept == 10) {
        continuing = false;
      } else {
        // Nothing intereseting is going on wait it out.
        PlatformThread::Sleep(automation::kSleepTime);
        times_slept++;
      }
    } else {
      times_slept = 0;
    }

    EXPECT_GE(new_popup_window_count, popup_window_count);
    EXPECT_LE(new_popup_window_count, kMaxPopupWindows);
    popup_window_count = new_popup_window_count;
  }
}

// Make sure that we refuse to close windows when a constrained popup is
// displayed.
TEST_F(BlockedPopupContainerInteractiveTest, WindowOpenWindowClosePopup) {
  NavigateMainTabTo(L"openclose_main.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000));

  // Make sure we have a blocked popup notification
  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());
  ASSERT_TRUE(popup_tab->WaitForBlockedPopupCountToChangeTo(1, 1000));

  // Ensure we didn't close the first popup window.
  ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 3000));
}

TEST_F(BlockedPopupContainerInteractiveTest, BlockAlertFromBlockedPopup) {
  NavigateMainTabTo(L"block_alert.html");

  // Wait for there to be an app modal dialog (and fail if it's shown).
  ASSERT_FALSE(automation()->WaitForAppModalDialog(4000));

  // Ensure one browser window.
  int browser_window_count;
  ASSERT_TRUE(automation()->GetBrowserWindowCount(&browser_window_count));
  ASSERT_EQ(1, browser_window_count);

  // Ensure one blocked popup window: the popup didn't escape.
  int popup_count = 0;
  ASSERT_TRUE(tab_->GetBlockedPopupCount(&popup_count));
  ASSERT_EQ(1, popup_count);
}

TEST_F(BlockedPopupContainerInteractiveTest, ShowAlertFromNormalPopup) {
  NavigateMainTabTo(L"show_alert.html");
  SimulateClickInCenterOf(window_);

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 5000));

  scoped_refptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_refptr<WindowProxy> popup_window(popup_browser->GetWindow());
  ASSERT_TRUE(popup_window.get());
  scoped_refptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

#if defined(OS_LINUX)
  // It seems we have to wait a little bit for the widgets to spin up before
  // we can start clicking on them.
  PlatformThread::Sleep(500);
#endif

  SimulateClickInCenterOf(popup_window);

  // Wait for there to be an app modal dialog.
  ASSERT_TRUE(automation()->WaitForAppModalDialog(5000));
}

// Make sure that window focus works while creating a popup window so that we
// don't
TEST_F(BlockedPopupContainerInteractiveTest, DontBreakOnBlur) {
  NavigateMainTabTo(L"window_blur_test.html");
  SimulateClickInCenterOf(window_);

  // Wait for the popup window to open.
  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  // We popup shouldn't be closed by the onblur handler.
  ASSERT_FALSE(automation()->WaitForWindowCountToBecome(1, 1500));
}
<|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 "base/command_line.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigation) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationEvents1) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/navigation1")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationEvents2) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/navigation2")) << message_;
}
<commit_msg>Disable ExtensionApiTest.WebNavigationEvents1, flakily exceeds test 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 "base/command_line.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigation) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
}

// Disabled, flakily exceeds timeout, http://crbug.com/72165.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_WebNavigationEvents1) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/navigation1")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebNavigationEvents2) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("webnavigation/navigation2")) << message_;
}
<|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/notifications/desktop_notification_service.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/thread.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/child_process_host.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_object_proxy.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/scoped_pref_update.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/worker_host/worker_process_host.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"

using WebKit::WebNotificationPresenter;

// static
string16 DesktopNotificationService::CreateDataUrl(
    const GURL& icon_url, const string16& title, const string16& body) {
  int resource;
  string16 line_name;
  string16 line;
  std::vector<string16> subst;
  if (icon_url.is_valid()) {
    resource = IDR_NOTIFICATION_ICON_HTML;
    subst.push_back(UTF8ToUTF16(icon_url.spec()));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
  } else if (title.empty() || body.empty()) {
    resource = IDR_NOTIFICATION_1LINE_HTML;
    line = title.empty() ? body : title;
    // Strings are div names in the template file.
    line_name = title.empty() ? ASCIIToUTF16("description")
                              : ASCIIToUTF16("title");
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line_name))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line))));
  } else {
    resource = IDR_NOTIFICATION_2LINE_HTML;
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
  }

  const base::StringPiece template_html(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
          resource));

  if (template_html.empty()) {
    NOTREACHED() << "unable to load template. ID: " << resource;
    return string16();
  }

  string16 format_string = ASCIIToUTF16("data:text/html;charset=utf-8,"
                                        + template_html.as_string());
  return ReplaceStringPlaceholders(format_string, subst, NULL);
}

// A task object which calls the renderer to inform the web page that the
// permission request has completed.
class NotificationPermissionCallbackTask : public Task {
 public:
  NotificationPermissionCallbackTask(int process_id, int route_id,
      int request_id)
      : process_id_(process_id),
        route_id_(route_id),
        request_id_(request_id) {
  }

  virtual void Run() {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
    RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
    if (host)
      host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_));
  }

 private:
  int process_id_;
  int route_id_;
  int request_id_;
};

// The delegate for the infobar shown when an origin requests notification
// permissions.
class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  NotificationPermissionInfoBarDelegate(TabContents* contents,
                                        const GURL& origin,
                                        const std::wstring& display_name,
                                        int process_id,
                                        int route_id,
                                        int callback_context)
      : ConfirmInfoBarDelegate(contents),
        origin_(origin),
        display_name_(display_name),
        profile_(contents->profile()),
        process_id_(process_id),
        route_id_(route_id),
        callback_context_(callback_context),
        action_taken_(false) {
  }

  // Overridden from ConfirmInfoBarDelegate:
  virtual void InfoBarClosed() {
    if (!action_taken_)
      UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);

    ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      new NotificationPermissionCallbackTask(
          process_id_, route_id_, callback_context_));

    delete this;
  }

  virtual std::wstring GetMessageText() const {
    return l10n_util::GetStringF(IDS_NOTIFICATION_PERMISSIONS, display_name_);
  }

  virtual SkBitmap* GetIcon() const {
    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
       IDR_PRODUCT_ICON_32);
  }

  virtual int GetButtons() const {
    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
  }

  virtual std::wstring GetButtonLabel(InfoBarButton button) const {
    return button == BUTTON_OK ?
        l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_YES) :
        l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_NO);
  }

  virtual bool Accept() {
    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
    profile_->GetDesktopNotificationService()->GrantPermission(origin_);
    action_taken_ = true;
    return true;
  }

  virtual bool Cancel() {
    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
    profile_->GetDesktopNotificationService()->DenyPermission(origin_);
    action_taken_ = true;
    return true;
  }

 private:
  // The origin we are asking for permissions on.
  GURL origin_;

  // The display name for the origin to be displayed.  Will be different from
  // origin_ for extensions.
  std::wstring display_name_;

  // The Profile that we restore sessions from.
  Profile* profile_;

  // The callback information that tells us how to respond to javascript via
  // the correct RenderView.
  int process_id_;
  int route_id_;
  int callback_context_;

  // Whether the user clicked one of the buttons.
  bool action_taken_;

  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
};

DesktopNotificationService::DesktopNotificationService(Profile* profile,
    NotificationUIManager* ui_manager)
    : profile_(profile),
      ui_manager_(ui_manager) {
  InitPrefs();
  StartObserving();
}

DesktopNotificationService::~DesktopNotificationService() {
  StopObserving();
}

// Initialize the cache with the allowed and denied origins, or
// create the preferences if they don't exist yet.
void DesktopNotificationService::InitPrefs() {
  PrefService* prefs = profile_->GetPrefs();
  std::vector<GURL> allowed_origins;
  std::vector<GURL> denied_origins;

  if (!profile_->IsOffTheRecord()) {
    if (!prefs->FindPreference(prefs::kDesktopNotificationAllowedOrigins))
      prefs->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins);
    const ListValue* allowed_sites =
        prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
    if (allowed_sites)
      NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
                                                     &allowed_origins);

    if (!prefs->FindPreference(prefs::kDesktopNotificationDeniedOrigins))
      prefs->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins);
    const ListValue* denied_sites =
        prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
    if (denied_sites)
      NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
                                                     &denied_origins);
  }

  prefs_cache_ = new NotificationsPrefsCache();
  prefs_cache_->SetCacheAllowedOrigins(allowed_origins);
  prefs_cache_->SetCacheDeniedOrigins(denied_origins);
  prefs_cache_->set_is_initialized(true);
}

void DesktopNotificationService::StartObserving() {
  if (!profile_->IsOffTheRecord()) {
    PrefService* prefs = profile_->GetPrefs();
    prefs->AddPrefObserver(prefs::kDesktopNotificationAllowedOrigins, this);
    prefs->AddPrefObserver(prefs::kDesktopNotificationDeniedOrigins, this);
  }
}

void DesktopNotificationService::StopObserving() {
  if (!profile_->IsOffTheRecord()) {
    PrefService* prefs = profile_->GetPrefs();
    prefs->RemovePrefObserver(prefs::kDesktopNotificationAllowedOrigins, this);
    prefs->RemovePrefObserver(prefs::kDesktopNotificationDeniedOrigins, this);
  }
}

void DesktopNotificationService::GrantPermission(const GURL& origin) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  PersistPermissionChange(origin, true);

  // Schedule a cache update on the IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(
          prefs_cache_.get(), &NotificationsPrefsCache::CacheAllowedOrigin,
          origin));
}

void DesktopNotificationService::DenyPermission(const GURL& origin) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  PersistPermissionChange(origin, false);

  // Schedule a cache update on the IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(
          prefs_cache_.get(), &NotificationsPrefsCache::CacheDeniedOrigin,
          origin));
}

void DesktopNotificationService::Observe(NotificationType type,
                                         const NotificationSource& source,
                                         const NotificationDetails& details) {
  DCHECK(NotificationType::PREF_CHANGED == type);
  PrefService* prefs = profile_->GetPrefs();
  std::wstring* name = Details<std::wstring>(details).ptr();

  if (0 == name->compare(prefs::kDesktopNotificationAllowedOrigins)) {
    const ListValue* allowed_sites =
        prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
    std::vector<GURL> allowed_origins;
    NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
                                                   &allowed_origins);
    // Schedule a cache update on the IO thread.
    ChromeThread::PostTask(
        ChromeThread::IO, FROM_HERE,
        NewRunnableMethod(
            prefs_cache_.get(),
            &NotificationsPrefsCache::SetCacheAllowedOrigins,
            allowed_origins));
  } else if (0 == name->compare(prefs::kDesktopNotificationDeniedOrigins)) {
    const ListValue* denied_sites =
        prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
    std::vector<GURL> denied_origins;
    NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
                                                   &denied_origins);
    // Schedule a cache update on the IO thread.
    ChromeThread::PostTask(
        ChromeThread::IO, FROM_HERE,
        NewRunnableMethod(
            prefs_cache_.get(),
            &NotificationsPrefsCache::SetCacheDeniedOrigins,
            denied_origins));
  }
}

void DesktopNotificationService::PersistPermissionChange(
    const GURL& origin, bool is_allowed) {
  // Don't persist changes when off the record.
  if (profile_->IsOffTheRecord())
    return;

  PrefService* prefs = profile_->GetPrefs();

  StopObserving();

  bool allowed_changed = false;
  bool denied_changed = false;

  ListValue* allowed_sites =
      prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
  ListValue* denied_sites =
      prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
  {
    // value is passed to the preferences list, or deleted.
    StringValue* value = new StringValue(origin.spec());

    // Remove from one list and add to the other.
    if (is_allowed) {
      // Remove from the denied list.
      if (denied_sites->Remove(*value) != -1)
        denied_changed = true;

      // Add to the allowed list.
      if (allowed_sites->AppendIfNotPresent(value))
        allowed_changed = true;
      else
        delete value;
    } else {
      // Remove from the allowed list.
      if (allowed_sites->Remove(*value) != -1)
        allowed_changed = true;

      // Add to the denied list.
      if (denied_sites->AppendIfNotPresent(value))
        denied_changed = true;
      else
        delete value;
    }
  }

  // Persist the pref if anthing changed, but only send updates for the
  // list that changed.
  if (allowed_changed || denied_changed) {
    if (allowed_changed) {
      ScopedPrefUpdate updateAllowed(
          prefs, prefs::kDesktopNotificationAllowedOrigins);
    }
    if (denied_changed) {
      ScopedPrefUpdate updateDenied(
          prefs, prefs::kDesktopNotificationDeniedOrigins);
    }
    prefs->ScheduleSavePersistentPrefs();
  }
  StartObserving();
}

void DesktopNotificationService::RequestPermission(
    const GURL& origin, int process_id, int route_id, int callback_context) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  // Show an info bar requesting permission.
  Browser* browser = BrowserList::GetLastActive();
  if (!browser) {
    // Reached during ui tests.
    return;
  }
  TabContents* tab = browser->GetSelectedTabContents();
  if (!tab)
    return;

  std::wstring display_name = DisplayNameForOrigin(origin);

  tab->AddInfoBar(new NotificationPermissionInfoBarDelegate(
      tab, origin, display_name, process_id, route_id, callback_context));
}

void DesktopNotificationService::ShowNotification(
    const Notification& notification) {
  ui_manager_->Add(notification, profile_);
}

bool DesktopNotificationService::CancelDesktopNotification(
    int process_id, int route_id, int notification_id) {
  scoped_refptr<NotificationObjectProxy> proxy(
      new NotificationObjectProxy(process_id, route_id, notification_id,
                                  false));
  Notification notif(GURL(), GURL(), L"", proxy);
  return ui_manager_->Cancel(notif);
}

bool DesktopNotificationService::ShowDesktopNotification(
    const GURL& origin, const GURL& url, int process_id, int route_id,
    DesktopNotificationSource source, int notification_id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  NotificationObjectProxy* proxy =
      new NotificationObjectProxy(process_id, route_id,
                                  notification_id,
                                  source == WorkerNotification);
  Notification notif(origin, url, DisplayNameForOrigin(origin), proxy);
  ShowNotification(notif);
  return true;
}

bool DesktopNotificationService::ShowDesktopNotificationText(
    const GURL& origin, const GURL& icon, const string16& title,
    const string16& text, int process_id, int route_id,
    DesktopNotificationSource source, int notification_id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  NotificationObjectProxy* proxy =
      new NotificationObjectProxy(process_id, route_id,
                                  notification_id,
                                  source == WorkerNotification);
  // "upconvert" the string parameters to a data: URL.
  string16 data_url = CreateDataUrl(icon, title, text);
  Notification notif(
      origin, GURL(data_url), DisplayNameForOrigin(origin), proxy);
  ShowNotification(notif);
  return true;
}

std::wstring DesktopNotificationService::DisplayNameForOrigin(
    const GURL& origin) {
  // If the source is an extension, lookup the display name.
  if (origin.SchemeIs(chrome::kExtensionScheme)) {
    ExtensionsService* ext_service = profile_->GetExtensionsService();
    if (ext_service) {
      Extension* extension = ext_service->GetExtensionByURL(origin);
      if (extension)
        return ASCIIToWide(extension->name());
    }
  }
  return UTF8ToWide(origin.host());
}
<commit_msg>Fix crash when signing in with certain desktop notification settings.<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/notifications/desktop_notification_service.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/thread.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/child_process_host.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_object_proxy.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/scoped_pref_update.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/worker_host/worker_process_host.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"

using WebKit::WebNotificationPresenter;

// static
string16 DesktopNotificationService::CreateDataUrl(
    const GURL& icon_url, const string16& title, const string16& body) {
  int resource;
  string16 line_name;
  string16 line;
  std::vector<string16> subst;
  if (icon_url.is_valid()) {
    resource = IDR_NOTIFICATION_ICON_HTML;
    subst.push_back(UTF8ToUTF16(icon_url.spec()));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
  } else if (title.empty() || body.empty()) {
    resource = IDR_NOTIFICATION_1LINE_HTML;
    line = title.empty() ? body : title;
    // Strings are div names in the template file.
    line_name = title.empty() ? ASCIIToUTF16("description")
                              : ASCIIToUTF16("title");
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line_name))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line))));
  } else {
    resource = IDR_NOTIFICATION_2LINE_HTML;
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
  }

  const base::StringPiece template_html(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
          resource));

  if (template_html.empty()) {
    NOTREACHED() << "unable to load template. ID: " << resource;
    return string16();
  }

  string16 format_string = ASCIIToUTF16("data:text/html;charset=utf-8,"
                                        + template_html.as_string());
  return ReplaceStringPlaceholders(format_string, subst, NULL);
}

// A task object which calls the renderer to inform the web page that the
// permission request has completed.
class NotificationPermissionCallbackTask : public Task {
 public:
  NotificationPermissionCallbackTask(int process_id, int route_id,
      int request_id)
      : process_id_(process_id),
        route_id_(route_id),
        request_id_(request_id) {
  }

  virtual void Run() {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
    RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
    if (host)
      host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_));
  }

 private:
  int process_id_;
  int route_id_;
  int request_id_;
};

// The delegate for the infobar shown when an origin requests notification
// permissions.
class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  NotificationPermissionInfoBarDelegate(TabContents* contents,
                                        const GURL& origin,
                                        const std::wstring& display_name,
                                        int process_id,
                                        int route_id,
                                        int callback_context)
      : ConfirmInfoBarDelegate(contents),
        origin_(origin),
        display_name_(display_name),
        profile_(contents->profile()),
        process_id_(process_id),
        route_id_(route_id),
        callback_context_(callback_context),
        action_taken_(false) {
  }

  // Overridden from ConfirmInfoBarDelegate:
  virtual void InfoBarClosed() {
    if (!action_taken_)
      UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);

    ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      new NotificationPermissionCallbackTask(
          process_id_, route_id_, callback_context_));

    delete this;
  }

  virtual std::wstring GetMessageText() const {
    return l10n_util::GetStringF(IDS_NOTIFICATION_PERMISSIONS, display_name_);
  }

  virtual SkBitmap* GetIcon() const {
    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
       IDR_PRODUCT_ICON_32);
  }

  virtual int GetButtons() const {
    return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
  }

  virtual std::wstring GetButtonLabel(InfoBarButton button) const {
    return button == BUTTON_OK ?
        l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_YES) :
        l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_NO);
  }

  virtual bool Accept() {
    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
    profile_->GetDesktopNotificationService()->GrantPermission(origin_);
    action_taken_ = true;
    return true;
  }

  virtual bool Cancel() {
    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
    profile_->GetDesktopNotificationService()->DenyPermission(origin_);
    action_taken_ = true;
    return true;
  }

 private:
  // The origin we are asking for permissions on.
  GURL origin_;

  // The display name for the origin to be displayed.  Will be different from
  // origin_ for extensions.
  std::wstring display_name_;

  // The Profile that we restore sessions from.
  Profile* profile_;

  // The callback information that tells us how to respond to javascript via
  // the correct RenderView.
  int process_id_;
  int route_id_;
  int callback_context_;

  // Whether the user clicked one of the buttons.
  bool action_taken_;

  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
};

DesktopNotificationService::DesktopNotificationService(Profile* profile,
    NotificationUIManager* ui_manager)
    : profile_(profile),
      ui_manager_(ui_manager) {
  InitPrefs();
  StartObserving();
}

DesktopNotificationService::~DesktopNotificationService() {
  StopObserving();
}

// Initialize the cache with the allowed and denied origins, or
// create the preferences if they don't exist yet.
void DesktopNotificationService::InitPrefs() {
  PrefService* prefs = profile_->GetPrefs();
  std::vector<GURL> allowed_origins;
  std::vector<GURL> denied_origins;

  if (!profile_->IsOffTheRecord()) {
    if (!prefs->FindPreference(prefs::kDesktopNotificationAllowedOrigins))
      prefs->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins);
    const ListValue* allowed_sites =
        prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
    if (allowed_sites)
      NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
                                                     &allowed_origins);

    if (!prefs->FindPreference(prefs::kDesktopNotificationDeniedOrigins))
      prefs->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins);
    const ListValue* denied_sites =
        prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
    if (denied_sites)
      NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
                                                     &denied_origins);
  }

  prefs_cache_ = new NotificationsPrefsCache();
  prefs_cache_->SetCacheAllowedOrigins(allowed_origins);
  prefs_cache_->SetCacheDeniedOrigins(denied_origins);
  prefs_cache_->set_is_initialized(true);
}

void DesktopNotificationService::StartObserving() {
  if (!profile_->IsOffTheRecord()) {
    PrefService* prefs = profile_->GetPrefs();
    prefs->AddPrefObserver(prefs::kDesktopNotificationAllowedOrigins, this);
    prefs->AddPrefObserver(prefs::kDesktopNotificationDeniedOrigins, this);
  }
}

void DesktopNotificationService::StopObserving() {
  if (!profile_->IsOffTheRecord()) {
    PrefService* prefs = profile_->GetPrefs();
    prefs->RemovePrefObserver(prefs::kDesktopNotificationAllowedOrigins, this);
    prefs->RemovePrefObserver(prefs::kDesktopNotificationDeniedOrigins, this);
  }
}

void DesktopNotificationService::GrantPermission(const GURL& origin) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  PersistPermissionChange(origin, true);

  // Schedule a cache update on the IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(
          prefs_cache_.get(), &NotificationsPrefsCache::CacheAllowedOrigin,
          origin));
}

void DesktopNotificationService::DenyPermission(const GURL& origin) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  PersistPermissionChange(origin, false);

  // Schedule a cache update on the IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(
          prefs_cache_.get(), &NotificationsPrefsCache::CacheDeniedOrigin,
          origin));
}

void DesktopNotificationService::Observe(NotificationType type,
                                         const NotificationSource& source,
                                         const NotificationDetails& details) {
  DCHECK(NotificationType::PREF_CHANGED == type);
  PrefService* prefs = profile_->GetPrefs();
  std::wstring* name = Details<std::wstring>(details).ptr();

  if (0 == name->compare(prefs::kDesktopNotificationAllowedOrigins)) {
    const ListValue* allowed_sites =
        prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
    std::vector<GURL> allowed_origins;
    if (allowed_sites) {
      NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
                                                     &allowed_origins);
    }
    // Schedule a cache update on the IO thread.
    ChromeThread::PostTask(
        ChromeThread::IO, FROM_HERE,
        NewRunnableMethod(
            prefs_cache_.get(),
            &NotificationsPrefsCache::SetCacheAllowedOrigins,
            allowed_origins));
  } else if (0 == name->compare(prefs::kDesktopNotificationDeniedOrigins)) {
    const ListValue* denied_sites =
        prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
    std::vector<GURL> denied_origins;
    if (denied_sites) {
      NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
                                                     &denied_origins);
    }
    // Schedule a cache update on the IO thread.
    ChromeThread::PostTask(
        ChromeThread::IO, FROM_HERE,
        NewRunnableMethod(
            prefs_cache_.get(),
            &NotificationsPrefsCache::SetCacheDeniedOrigins,
            denied_origins));
  }
}

void DesktopNotificationService::PersistPermissionChange(
    const GURL& origin, bool is_allowed) {
  // Don't persist changes when off the record.
  if (profile_->IsOffTheRecord())
    return;

  PrefService* prefs = profile_->GetPrefs();

  StopObserving();

  bool allowed_changed = false;
  bool denied_changed = false;

  ListValue* allowed_sites =
      prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
  ListValue* denied_sites =
      prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
  {
    // value is passed to the preferences list, or deleted.
    StringValue* value = new StringValue(origin.spec());

    // Remove from one list and add to the other.
    if (is_allowed) {
      // Remove from the denied list.
      if (denied_sites->Remove(*value) != -1)
        denied_changed = true;

      // Add to the allowed list.
      if (allowed_sites->AppendIfNotPresent(value))
        allowed_changed = true;
      else
        delete value;
    } else {
      // Remove from the allowed list.
      if (allowed_sites->Remove(*value) != -1)
        allowed_changed = true;

      // Add to the denied list.
      if (denied_sites->AppendIfNotPresent(value))
        denied_changed = true;
      else
        delete value;
    }
  }

  // Persist the pref if anthing changed, but only send updates for the
  // list that changed.
  if (allowed_changed || denied_changed) {
    if (allowed_changed) {
      ScopedPrefUpdate updateAllowed(
          prefs, prefs::kDesktopNotificationAllowedOrigins);
    }
    if (denied_changed) {
      ScopedPrefUpdate updateDenied(
          prefs, prefs::kDesktopNotificationDeniedOrigins);
    }
    prefs->ScheduleSavePersistentPrefs();
  }
  StartObserving();
}

void DesktopNotificationService::RequestPermission(
    const GURL& origin, int process_id, int route_id, int callback_context) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  // Show an info bar requesting permission.
  Browser* browser = BrowserList::GetLastActive();
  if (!browser) {
    // Reached during ui tests.
    return;
  }
  TabContents* tab = browser->GetSelectedTabContents();
  if (!tab)
    return;

  std::wstring display_name = DisplayNameForOrigin(origin);

  tab->AddInfoBar(new NotificationPermissionInfoBarDelegate(
      tab, origin, display_name, process_id, route_id, callback_context));
}

void DesktopNotificationService::ShowNotification(
    const Notification& notification) {
  ui_manager_->Add(notification, profile_);
}

bool DesktopNotificationService::CancelDesktopNotification(
    int process_id, int route_id, int notification_id) {
  scoped_refptr<NotificationObjectProxy> proxy(
      new NotificationObjectProxy(process_id, route_id, notification_id,
                                  false));
  Notification notif(GURL(), GURL(), L"", proxy);
  return ui_manager_->Cancel(notif);
}

bool DesktopNotificationService::ShowDesktopNotification(
    const GURL& origin, const GURL& url, int process_id, int route_id,
    DesktopNotificationSource source, int notification_id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  NotificationObjectProxy* proxy =
      new NotificationObjectProxy(process_id, route_id,
                                  notification_id,
                                  source == WorkerNotification);
  Notification notif(origin, url, DisplayNameForOrigin(origin), proxy);
  ShowNotification(notif);
  return true;
}

bool DesktopNotificationService::ShowDesktopNotificationText(
    const GURL& origin, const GURL& icon, const string16& title,
    const string16& text, int process_id, int route_id,
    DesktopNotificationSource source, int notification_id) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  NotificationObjectProxy* proxy =
      new NotificationObjectProxy(process_id, route_id,
                                  notification_id,
                                  source == WorkerNotification);
  // "upconvert" the string parameters to a data: URL.
  string16 data_url = CreateDataUrl(icon, title, text);
  Notification notif(
      origin, GURL(data_url), DisplayNameForOrigin(origin), proxy);
  ShowNotification(notif);
  return true;
}

std::wstring DesktopNotificationService::DisplayNameForOrigin(
    const GURL& origin) {
  // If the source is an extension, lookup the display name.
  if (origin.SchemeIs(chrome::kExtensionScheme)) {
    ExtensionsService* ext_service = profile_->GetExtensionsService();
    if (ext_service) {
      Extension* extension = ext_service->GetExtensionByURL(origin);
      if (extension)
        return ASCIIToWide(extension->name());
    }
  }
  return UTF8ToWide(origin.host());
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "net/socket/tcp_client_socket_pool.h"

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "net/base/net_errors.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/tcp_client_socket.h"

using base::TimeDelta;

namespace {

// The timeout value, in seconds, used to clean up idle sockets that can't be
// reused.
//
// Note: It's important to close idle sockets that have received data as soon
// as possible because the received data may cause BSOD on Windows XP under
// some conditions.  See http://crbug.com/4606.
const int kCleanupInterval = 10;  // DO NOT INCREASE THIS TIMEOUT.

// The maximum duration, in seconds, to keep idle persistent sockets alive.
const int kIdleTimeout = 300;  // 5 minutes.

}  // namespace

namespace net {

TCPConnectJob::TCPConnectJob(
    const std::string& group_name,
    const HostResolver::RequestInfo& resolve_info,
    const ClientSocketHandle* handle,
    ClientSocketFactory* client_socket_factory,
    ClientSocketPoolBase* pool)
    : group_name_(group_name),
      resolve_info_(resolve_info),
      handle_(handle),
      client_socket_factory_(client_socket_factory),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          callback_(this,
                    &TCPConnectJob::OnIOComplete)),
      pool_(pool),
      resolver_(pool->GetHostResolver()) {}

TCPConnectJob::~TCPConnectJob() {
  // We don't worry about cancelling the host resolution and TCP connect, since
  // ~SingleRequestHostResolver and ~ClientSocket will take care of it.
}

int TCPConnectJob::Connect() {
  int rv = resolver_.Resolve(resolve_info_, &addresses_, &callback_);
  if (rv != ERR_IO_PENDING)
    rv = OnIOCompleteInternal(rv, true /* synchronous */);
  return rv;
}

void TCPConnectJob::OnIOComplete(int result) {
  OnIOCompleteInternal(result, false /* asynchronous */);
}

int TCPConnectJob::OnIOCompleteInternal(
    int result, bool synchronous) {
  CHECK(result != ERR_IO_PENDING);

  ClientSocketPoolBase::Request* request = pool_->GetConnectingRequest(
      group_name_, handle_);
  CHECK(request);

  if (result == OK && request->load_state == LOAD_STATE_RESOLVING_HOST) {
    request->load_state = LOAD_STATE_CONNECTING;
    socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
    connect_start_time_ = base::TimeTicks::Now();
    result = socket_->Connect(&callback_);
    if (result == ERR_IO_PENDING)
      return result;
  }

  if (result == OK) {
    CHECK(request->load_state == LOAD_STATE_CONNECTING);
    CHECK(connect_start_time_ != base::TimeTicks());
    base::TimeDelta connect_duration =
        base::TimeTicks::Now() - connect_start_time_;

    UMA_HISTOGRAM_CLIPPED_TIMES("Net.TCP_Connection_Latency",
        connect_duration,
        base::TimeDelta::FromMilliseconds(1),
        base::TimeDelta::FromMinutes(10),
        100);
  }

  // Now, we either succeeded at Connect()'ing, or we failed at host resolution
  // or Connect()'ing.  Either way, we'll run the callback to alert the client.

  CompletionCallback* callback = NULL;

  if (result == OK) {
    callback = pool_->OnConnectingRequestComplete(
        group_name_,
        handle_,
        false /* don't deactivate socket */,
        socket_.release());
  } else {
    callback = pool_->OnConnectingRequestComplete(
        group_name_,
        handle_,
        true /* deactivate socket */,
        NULL /* no connected socket to give */);
  }

  // |this| is deleted after this point.

  CHECK(callback);

  if (!synchronous)
    callback->Run(result);
  return result;
}

ConnectJob* TCPClientSocketPool::TCPConnectJobFactory::NewConnectJob(
    const std::string& group_name,
    const ClientSocketPoolBase::Request& request,
    ClientSocketPoolBase* pool) const {
  return new TCPConnectJob(
      group_name, request.resolve_info, request.handle,
      client_socket_factory_, pool);
}

TCPClientSocketPool::TCPClientSocketPool(
    int max_sockets_per_group,
    HostResolver* host_resolver,
    ClientSocketFactory* client_socket_factory)
    : base_(new ClientSocketPoolBase(
        max_sockets_per_group, host_resolver,
        new TCPConnectJobFactory(client_socket_factory))) {}

TCPClientSocketPool::~TCPClientSocketPool() {}

int TCPClientSocketPool::RequestSocket(
    const std::string& group_name,
    const HostResolver::RequestInfo& resolve_info,
    int priority,
    ClientSocketHandle* handle,
    CompletionCallback* callback) {
  return base_->RequestSocket(
      group_name, resolve_info, priority, handle, callback);
}

void TCPClientSocketPool::CancelRequest(
    const std::string& group_name,
    const ClientSocketHandle* handle) {
  base_->CancelRequest(group_name, handle);
}

void TCPClientSocketPool::ReleaseSocket(
    const std::string& group_name,
    ClientSocket* socket) {
  base_->ReleaseSocket(group_name, socket);
}

void TCPClientSocketPool::CloseIdleSockets() {
  base_->CloseIdleSockets();
}

int TCPClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return base_->IdleSocketCountInGroup(group_name);
}

LoadState TCPClientSocketPool::GetLoadState(
    const std::string& group_name, const ClientSocketHandle* handle) const {
  return base_->GetLoadState(group_name, handle);
}

}  // namespace net
<commit_msg>Remove some dead code -- this was moved into client_socket_pool_base.cc.<commit_after>// Copyright (c) 2006-2008 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 "net/socket/tcp_client_socket_pool.h"

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "net/base/net_errors.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/tcp_client_socket.h"

using base::TimeDelta;

namespace net {

TCPConnectJob::TCPConnectJob(
    const std::string& group_name,
    const HostResolver::RequestInfo& resolve_info,
    const ClientSocketHandle* handle,
    ClientSocketFactory* client_socket_factory,
    ClientSocketPoolBase* pool)
    : group_name_(group_name),
      resolve_info_(resolve_info),
      handle_(handle),
      client_socket_factory_(client_socket_factory),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          callback_(this,
                    &TCPConnectJob::OnIOComplete)),
      pool_(pool),
      resolver_(pool->GetHostResolver()) {}

TCPConnectJob::~TCPConnectJob() {
  // We don't worry about cancelling the host resolution and TCP connect, since
  // ~SingleRequestHostResolver and ~ClientSocket will take care of it.
}

int TCPConnectJob::Connect() {
  int rv = resolver_.Resolve(resolve_info_, &addresses_, &callback_);
  if (rv != ERR_IO_PENDING)
    rv = OnIOCompleteInternal(rv, true /* synchronous */);
  return rv;
}

void TCPConnectJob::OnIOComplete(int result) {
  OnIOCompleteInternal(result, false /* asynchronous */);
}

int TCPConnectJob::OnIOCompleteInternal(
    int result, bool synchronous) {
  CHECK(result != ERR_IO_PENDING);

  ClientSocketPoolBase::Request* request = pool_->GetConnectingRequest(
      group_name_, handle_);
  CHECK(request);

  if (result == OK && request->load_state == LOAD_STATE_RESOLVING_HOST) {
    request->load_state = LOAD_STATE_CONNECTING;
    socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
    connect_start_time_ = base::TimeTicks::Now();
    result = socket_->Connect(&callback_);
    if (result == ERR_IO_PENDING)
      return result;
  }

  if (result == OK) {
    CHECK(request->load_state == LOAD_STATE_CONNECTING);
    CHECK(connect_start_time_ != base::TimeTicks());
    base::TimeDelta connect_duration =
        base::TimeTicks::Now() - connect_start_time_;

    UMA_HISTOGRAM_CLIPPED_TIMES("Net.TCP_Connection_Latency",
        connect_duration,
        base::TimeDelta::FromMilliseconds(1),
        base::TimeDelta::FromMinutes(10),
        100);
  }

  // Now, we either succeeded at Connect()'ing, or we failed at host resolution
  // or Connect()'ing.  Either way, we'll run the callback to alert the client.

  CompletionCallback* callback = NULL;

  if (result == OK) {
    callback = pool_->OnConnectingRequestComplete(
        group_name_,
        handle_,
        false /* don't deactivate socket */,
        socket_.release());
  } else {
    callback = pool_->OnConnectingRequestComplete(
        group_name_,
        handle_,
        true /* deactivate socket */,
        NULL /* no connected socket to give */);
  }

  // |this| is deleted after this point.

  CHECK(callback);

  if (!synchronous)
    callback->Run(result);
  return result;
}

ConnectJob* TCPClientSocketPool::TCPConnectJobFactory::NewConnectJob(
    const std::string& group_name,
    const ClientSocketPoolBase::Request& request,
    ClientSocketPoolBase* pool) const {
  return new TCPConnectJob(
      group_name, request.resolve_info, request.handle,
      client_socket_factory_, pool);
}

TCPClientSocketPool::TCPClientSocketPool(
    int max_sockets_per_group,
    HostResolver* host_resolver,
    ClientSocketFactory* client_socket_factory)
    : base_(new ClientSocketPoolBase(
        max_sockets_per_group, host_resolver,
        new TCPConnectJobFactory(client_socket_factory))) {}

TCPClientSocketPool::~TCPClientSocketPool() {}

int TCPClientSocketPool::RequestSocket(
    const std::string& group_name,
    const HostResolver::RequestInfo& resolve_info,
    int priority,
    ClientSocketHandle* handle,
    CompletionCallback* callback) {
  return base_->RequestSocket(
      group_name, resolve_info, priority, handle, callback);
}

void TCPClientSocketPool::CancelRequest(
    const std::string& group_name,
    const ClientSocketHandle* handle) {
  base_->CancelRequest(group_name, handle);
}

void TCPClientSocketPool::ReleaseSocket(
    const std::string& group_name,
    ClientSocket* socket) {
  base_->ReleaseSocket(group_name, socket);
}

void TCPClientSocketPool::CloseIdleSockets() {
  base_->CloseIdleSockets();
}

int TCPClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return base_->IdleSocketCountInGroup(group_name);
}

LoadState TCPClientSocketPool::GetLoadState(
    const std::string& group_name, const ClientSocketHandle* handle) const {
  return base_->GetLoadState(group_name, handle);
}

}  // namespace net
<|endoftext|>