<commit_before>#ifndef MONITOR_EXIT_HPP_
#define MONITOR_EXIT_HPP_

#include <chrono>
#include <vector>
#include <functional>

#include "../Monitor.hpp"

namespace aff3ct
{
namespace module
{
template <typename B = int, typename R = float>
class Monitor_EXIT : public Monitor
{
public:
	inline Task&   operator[](const mnt::tsk                    t) { return Module::operator[]((int)t);                                   }
	inline Socket& operator[](const mnt::sck::check_mutual_info s) { return Module::operator[]((int)mnt::tsk::check_mutual_info)[(int)s]; }

protected:

	R I_A_sum;
	unsigned long long n_trials;

	const unsigned max_n_trials;

	std::vector<std::function<void(void)>> callbacks_measure;

	std::vector<B> bits_buff;
	std::vector<R> llrs_e_buff;

	int N;

public:
	Monitor_EXIT(const int size, const unsigned max_n_trials, const int n_frames = 1);
	Monitor_EXIT(const Monitor_EXIT<B,R>& m, const int n_frames = -1); // construct with the same parameters than "m"
	Monitor_EXIT(); // construct with null and default parameters.

	virtual ~Monitor_EXIT() = default;

	int get_N() const;

	bool equivalent(const Monitor_EXIT<B,R>& m, bool do_throw = false) const; // check if this monitor and "m" have equivalent construction arguments
	                                                                          // and then can be merged by "collect" or "copy" methods

	/*!
	 * \brief Compares two messages and counts the number of frame errors and bit errors.
	 *
	 * Typically this method is called at the very end of a communication chain.
	 *
	 * \param U: the original message (from the Source or the CRC).
	 * \param V: the decoded message (from the Decoder).
	 */
	template <class AB = std::allocator<B>, class AR = std::allocator<R>>
	void check_mutual_info(const std::vector<B,AB>& bits,
	                       const std::vector<R,AR>& llrs_a,
	                       const std::vector<R,AR>& llrs_e,
	                       const int frame_id = -1)
	{
		if ((int)bits.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'bits.size()' has to be equal to 'size' * 'n_frames' ('bits.size()' = " << bits.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if ((int)llrs_a.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'llrs_a.size()' has to be equal to 'size' * 'n_frames' ('llrs_a.size()' = " << llrs_a.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if ((int)llrs_e.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'llrs_e.size()' has to be equal to 'size' * 'n_frames' ('llrs_e.size()' = " << llrs_e.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if (frame_id != -1 && frame_id >= this->n_frames)
		{
			std::stringstream message;
			message << "'frame_id' has to be equal to '-1' or to be smaller than 'n_frames' ('frame_id' = "
			        << frame_id << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		return this->check_mutual_info(bits.data(), llrs_a.data(), llrs_e.data(), frame_id);
	}

	virtual void check_mutual_info(const B *bits, const R *llrs_a, const R *llrs_e, const int frame_id = -1);

	unsigned get_n_trials_limit() const;

	virtual bool n_trials_achieved() const;

	virtual R get_I_E() const;
	virtual R get_I_A() const;

	virtual unsigned long long get_n_trials() const;

	virtual void add_handler_measure(std::function<void(void)> callback);

	virtual void reset();
	virtual void clear_callbacks();

	virtual void collect(const Monitor& m,         bool fully = false);
	virtual void collect(const Monitor_EXIT<B,R>& m, bool fully = false);

	Monitor_EXIT<B,R>& operator+=(const Monitor_EXIT<B,R>& m); // not full "collect" call

	virtual void copy(const Monitor& m,         bool fully = false);
	virtual void copy(const Monitor_EXIT<B,R>& m, bool fully = false);

	Monitor_EXIT<B,R>& operator=(const Monitor_EXIT<B,R>& m); // not full "copy" call

protected:
	virtual void _check_mutual_info_avg  (const B *bits, const R *llrs_a, const int frame_id);
	virtual R _check_mutual_info_histo() const;

#ifdef ENABLE_MPI
public:

	// static constexpr unsigned n_MPI_attributes = 3;
	struct Vals_mpi
	{
		int n_frames;

		R I_A_sum;
		unsigned long long n_trials;
		unsigned max_n_trials;

		int N;
	};

	// static void create_MPI_struct(int          blen         [n_MPI_attributes],
	//                               MPI_Aint     displacements[n_MPI_attributes],
	//                               MPI_Datatype oldtypes     [n_MPI_attributes]);

	Monitor_BFER(const Vals_mpi& v)
	: Monitor(v.n_frames),
	  I_A_sum(v.I_A_sum),
	  n_trials(v.n_trials),
	  max_n_trials(v.max_n_trials),
	  N(v.N)
	{

	}

	Vals_mpi get_vals_mpi() const
	{
		Vals_mpi v;

		v.n_frames     = this->n_frames;
		v.I_A_sum      = this->I_A_sum;
		v.n_trials     = this->n_trials;
		v.max_n_trials = this->max_n_trials;
		v.N            = this->N;

		return v;
	}

	virtual void copy(const Vals_mpi& v)
	{
		I_A_sum           = v.I_A_sum;
		n_trials = v.n_trials;
	}

#endif
};
}
}

#endif /* MONITOR_EXIT_HPP_ */
<commit_msg>Fix the monitor_exit constructor in MPI<commit_after>#ifndef MONITOR_EXIT_HPP_
#define MONITOR_EXIT_HPP_

#include <chrono>
#include <vector>
#include <functional>

#include "../Monitor.hpp"

namespace aff3ct
{
namespace module
{
template <typename B = int, typename R = float>
class Monitor_EXIT : public Monitor
{
public:
	inline Task&   operator[](const mnt::tsk                    t) { return Module::operator[]((int)t);                                   }
	inline Socket& operator[](const mnt::sck::check_mutual_info s) { return Module::operator[]((int)mnt::tsk::check_mutual_info)[(int)s]; }

protected:

	R I_A_sum;
	unsigned long long n_trials;

	const unsigned max_n_trials;

	std::vector<std::function<void(void)>> callbacks_measure;

	std::vector<B> bits_buff;
	std::vector<R> llrs_e_buff;

	int N;

public:
	Monitor_EXIT(const int size, const unsigned max_n_trials, const int n_frames = 1);
	Monitor_EXIT(const Monitor_EXIT<B,R>& m, const int n_frames = -1); // construct with the same parameters than "m"
	Monitor_EXIT(); // construct with null and default parameters.

	virtual ~Monitor_EXIT() = default;

	int get_N() const;

	bool equivalent(const Monitor_EXIT<B,R>& m, bool do_throw = false) const; // check if this monitor and "m" have equivalent construction arguments
	                                                                          // and then can be merged by "collect" or "copy" methods

	/*!
	 * \brief Compares two messages and counts the number of frame errors and bit errors.
	 *
	 * Typically this method is called at the very end of a communication chain.
	 *
	 * \param U: the original message (from the Source or the CRC).
	 * \param V: the decoded message (from the Decoder).
	 */
	template <class AB = std::allocator<B>, class AR = std::allocator<R>>
	void check_mutual_info(const std::vector<B,AB>& bits,
	                       const std::vector<R,AR>& llrs_a,
	                       const std::vector<R,AR>& llrs_e,
	                       const int frame_id = -1)
	{
		if ((int)bits.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'bits.size()' has to be equal to 'size' * 'n_frames' ('bits.size()' = " << bits.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if ((int)llrs_a.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'llrs_a.size()' has to be equal to 'size' * 'n_frames' ('llrs_a.size()' = " << llrs_a.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if ((int)llrs_e.size() != this->size * this->n_frames)
		{
			std::stringstream message;
			message << "'llrs_e.size()' has to be equal to 'size' * 'n_frames' ('llrs_e.size()' = " << llrs_e.size()
			        << ", 'size' = " << this->size << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		if (frame_id != -1 && frame_id >= this->n_frames)
		{
			std::stringstream message;
			message << "'frame_id' has to be equal to '-1' or to be smaller than 'n_frames' ('frame_id' = "
			        << frame_id << ", 'n_frames' = " << this->n_frames << ").";
			throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
		}

		return this->check_mutual_info(bits.data(), llrs_a.data(), llrs_e.data(), frame_id);
	}

	virtual void check_mutual_info(const B *bits, const R *llrs_a, const R *llrs_e, const int frame_id = -1);

	unsigned get_n_trials_limit() const;

	virtual bool n_trials_achieved() const;

	virtual R get_I_E() const;
	virtual R get_I_A() const;

	virtual unsigned long long get_n_trials() const;

	virtual void add_handler_measure(std::function<void(void)> callback);

	virtual void reset();
	virtual void clear_callbacks();

	virtual void collect(const Monitor& m,         bool fully = false);
	virtual void collect(const Monitor_EXIT<B,R>& m, bool fully = false);

	Monitor_EXIT<B,R>& operator+=(const Monitor_EXIT<B,R>& m); // not full "collect" call

	virtual void copy(const Monitor& m,         bool fully = false);
	virtual void copy(const Monitor_EXIT<B,R>& m, bool fully = false);

	Monitor_EXIT<B,R>& operator=(const Monitor_EXIT<B,R>& m); // not full "copy" call

protected:
	virtual void _check_mutual_info_avg  (const B *bits, const R *llrs_a, const int frame_id);
	virtual R _check_mutual_info_histo() const;

#ifdef ENABLE_MPI
public:

	// static constexpr unsigned n_MPI_attributes = 3;
	struct Vals_mpi
	{
		int n_frames;

		R I_A_sum;
		unsigned long long n_trials;
		unsigned max_n_trials;

		int N;
	};

	// static void create_MPI_struct(int          blen         [n_MPI_attributes],
	//                               MPI_Aint     displacements[n_MPI_attributes],
	//                               MPI_Datatype oldtypes     [n_MPI_attributes]);

	Monitor_EXIT(const Vals_mpi& v)
	: Monitor(v.n_frames),
	  I_A_sum(v.I_A_sum),
	  n_trials(v.n_trials),
	  max_n_trials(v.max_n_trials),
	  N(v.N)
	{

	}

	Vals_mpi get_vals_mpi() const
	{
		Vals_mpi v;

		v.n_frames     = this->n_frames;
		v.I_A_sum      = this->I_A_sum;
		v.n_trials     = this->n_trials;
		v.max_n_trials = this->max_n_trials;
		v.N            = this->N;

		return v;
	}

	virtual void copy(const Vals_mpi& v)
	{
		I_A_sum           = v.I_A_sum;
		n_trials = v.n_trials;
	}

#endif
};
}
}

#endif /* MONITOR_EXIT_HPP_ */
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
 * Copyright (C) 2007-2009 Torch Mobile, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "wtf/text/TextEncoding.h"

#include "wtf/text/TextEncodingRegistry.h"
#include <unicode/unorm.h>
#include "wtf/OwnPtr.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Threading.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"

namespace WTF {

static const TextEncoding& UTF7Encoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF7Encoding = *new TextEncoding("UTF-7"));
    return globalUTF7Encoding;
}

TextEncoding::TextEncoding(const char* name)
    : m_name(atomicCanonicalTextEncodingName(name))
{
    // Aliases are valid, but not "replacement" itself.
    if (m_name && isReplacementEncoding(name))
        m_name = 0;
}

TextEncoding::TextEncoding(const String& name)
    : m_name(atomicCanonicalTextEncodingName(name))
{
    // Aliases are valid, but not "replacement" itself.
    if (m_name && isReplacementEncoding(name))
        m_name = 0;
}

String TextEncoding::decode(const char* data, size_t length, bool stopOnError, bool& sawError) const
{
    if (!m_name)
        return String();

    return newTextCodec(*this)->decode(data, length, DataEOF, stopOnError, sawError);
}

CString TextEncoding::encode(const String& string, UnencodableHandling handling) const
{
    if (!m_name)
        return CString();

    if (string.isEmpty())
        return "";

    OwnPtr<TextCodec> textCodec = newTextCodec(*this);
    CString encodedString;
    if (string.is8Bit())
        encodedString = textCodec->encode(string.characters8(), string.length(), handling);
    else
        encodedString = textCodec->encode(string.characters16(), string.length(), handling);
    return encodedString;
}

CString TextEncoding::normalizeAndEncode(const String& string, UnencodableHandling handling) const
{
    if (!m_name)
        return CString();

    if (string.isEmpty())
        return "";

    // Text exclusively containing Latin-1 characters (U+0000..U+00FF) is left
    // unaffected by NFC. This is effectively the same as saying that all
    // Latin-1 text is already normalized to NFC.
    // Source: http://unicode.org/reports/tr15/
    if (string.is8Bit())
        return newTextCodec(*this)->encode(string.characters8(), string.length(), handling);

    const UChar* source = string.characters16();
    size_t length = string.length();

    Vector<UChar> normalizedCharacters;

    UErrorCode err = U_ZERO_ERROR;
    if (unorm_quickCheck(source, length, UNORM_NFC, &err) != UNORM_YES) {
        // First try using the length of the original string, since normalization to NFC rarely increases length.
        normalizedCharacters.grow(length);
        int32_t normalizedLength = unorm_normalize(source, length, UNORM_NFC, 0, normalizedCharacters.data(), length, &err);
        if (err == U_BUFFER_OVERFLOW_ERROR) {
            err = U_ZERO_ERROR;
            normalizedCharacters.resize(normalizedLength);
            normalizedLength = unorm_normalize(source, length, UNORM_NFC, 0, normalizedCharacters.data(), normalizedLength, &err);
        }
        ASSERT(U_SUCCESS(err));

        source = normalizedCharacters.data();
        length = normalizedLength;
    }

    return newTextCodec(*this)->encode(source, length, handling);
}

bool TextEncoding::usesVisualOrdering() const
{
    if (noExtendedTextEncodingNameUsed())
        return false;

    static const char* const a = atomicCanonicalTextEncodingName("ISO-8859-8");
    return m_name == a;
}

bool TextEncoding::isNonByteBasedEncoding() const
{
    if (noExtendedTextEncodingNameUsed()) {
        return *this == UTF16LittleEndianEncoding()
            || *this == UTF16BigEndianEncoding();
    }

    return *this == UTF16LittleEndianEncoding()
        || *this == UTF16BigEndianEncoding()
        || *this == UTF32BigEndianEncoding()
        || *this == UTF32LittleEndianEncoding();
}

bool TextEncoding::isUTF7Encoding() const
{
    if (noExtendedTextEncodingNameUsed())
        return false;

    return *this == UTF7Encoding();
}

const TextEncoding& TextEncoding::closestByteBasedEquivalent() const
{
    if (isNonByteBasedEncoding())
        return UTF8Encoding();
    return *this;
}

// HTML5 specifies that UTF-8 be used in form submission when a form is
// is a part of a document in UTF-16 probably because UTF-16 is not a
// byte-based encoding and can contain 0x00. By extension, the same
// should be done for UTF-32. In case of UTF-7, it is a byte-based encoding,
// but it's fraught with problems and we'd rather steer clear of it.
const TextEncoding& TextEncoding::encodingForFormSubmission() const
{
    if (isNonByteBasedEncoding() || isUTF7Encoding())
        return UTF8Encoding();
    return *this;
}

const TextEncoding& ASCIIEncoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalASCIIEncoding = *new TextEncoding("ASCII"));
    return globalASCIIEncoding;
}

const TextEncoding& Latin1Encoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalLatin1Encoding = *new TextEncoding("latin1"));
    return globalLatin1Encoding;
}

const TextEncoding& UTF16BigEndianEncoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF16BigEndianEncoding = *new TextEncoding("UTF-16BE"));
    return globalUTF16BigEndianEncoding;
}

const TextEncoding& UTF16LittleEndianEncoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF16LittleEndianEncoding = *new TextEncoding("UTF-16LE"));
    return globalUTF16LittleEndianEncoding;
}

const TextEncoding& UTF32BigEndianEncoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF32BigEndianEncoding = *new TextEncoding("UTF-32BE"));
    return globalUTF32BigEndianEncoding;
}

const TextEncoding& UTF32LittleEndianEncoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF32LittleEndianEncoding = *new TextEncoding("UTF-32LE"));
    return globalUTF32LittleEndianEncoding;
}

const TextEncoding& UTF8Encoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalUTF8Encoding = *new TextEncoding("UTF-8"));
    ASSERT(globalUTF8Encoding.isValid());
    return globalUTF8Encoding;
}

const TextEncoding& WindowsLatin1Encoding()
{
    AtomicallyInitializedStatic(TextEncoding, globalWindowsLatin1Encoding = *new TextEncoding("WinLatin1"));
    return globalWindowsLatin1Encoding;
}

} // namespace WTF
<commit_msg>Keep a reference to new'ed TextEncoding singletons.<commit_after>/*
 * Copyright (C) 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
 * Copyright (C) 2007-2009 Torch Mobile, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "wtf/text/TextEncoding.h"

#include "wtf/text/TextEncodingRegistry.h"
#include <unicode/unorm.h>
#include "wtf/OwnPtr.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Threading.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"

namespace WTF {

static const TextEncoding& UTF7Encoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF7Encoding = *new TextEncoding("UTF-7"));
    return globalUTF7Encoding;
}

TextEncoding::TextEncoding(const char* name)
    : m_name(atomicCanonicalTextEncodingName(name))
{
    // Aliases are valid, but not "replacement" itself.
    if (m_name && isReplacementEncoding(name))
        m_name = 0;
}

TextEncoding::TextEncoding(const String& name)
    : m_name(atomicCanonicalTextEncodingName(name))
{
    // Aliases are valid, but not "replacement" itself.
    if (m_name && isReplacementEncoding(name))
        m_name = 0;
}

String TextEncoding::decode(const char* data, size_t length, bool stopOnError, bool& sawError) const
{
    if (!m_name)
        return String();

    return newTextCodec(*this)->decode(data, length, DataEOF, stopOnError, sawError);
}

CString TextEncoding::encode(const String& string, UnencodableHandling handling) const
{
    if (!m_name)
        return CString();

    if (string.isEmpty())
        return "";

    OwnPtr<TextCodec> textCodec = newTextCodec(*this);
    CString encodedString;
    if (string.is8Bit())
        encodedString = textCodec->encode(string.characters8(), string.length(), handling);
    else
        encodedString = textCodec->encode(string.characters16(), string.length(), handling);
    return encodedString;
}

CString TextEncoding::normalizeAndEncode(const String& string, UnencodableHandling handling) const
{
    if (!m_name)
        return CString();

    if (string.isEmpty())
        return "";

    // Text exclusively containing Latin-1 characters (U+0000..U+00FF) is left
    // unaffected by NFC. This is effectively the same as saying that all
    // Latin-1 text is already normalized to NFC.
    // Source: http://unicode.org/reports/tr15/
    if (string.is8Bit())
        return newTextCodec(*this)->encode(string.characters8(), string.length(), handling);

    const UChar* source = string.characters16();
    size_t length = string.length();

    Vector<UChar> normalizedCharacters;

    UErrorCode err = U_ZERO_ERROR;
    if (unorm_quickCheck(source, length, UNORM_NFC, &err) != UNORM_YES) {
        // First try using the length of the original string, since normalization to NFC rarely increases length.
        normalizedCharacters.grow(length);
        int32_t normalizedLength = unorm_normalize(source, length, UNORM_NFC, 0, normalizedCharacters.data(), length, &err);
        if (err == U_BUFFER_OVERFLOW_ERROR) {
            err = U_ZERO_ERROR;
            normalizedCharacters.resize(normalizedLength);
            normalizedLength = unorm_normalize(source, length, UNORM_NFC, 0, normalizedCharacters.data(), normalizedLength, &err);
        }
        ASSERT(U_SUCCESS(err));

        source = normalizedCharacters.data();
        length = normalizedLength;
    }

    return newTextCodec(*this)->encode(source, length, handling);
}

bool TextEncoding::usesVisualOrdering() const
{
    if (noExtendedTextEncodingNameUsed())
        return false;

    static const char* const a = atomicCanonicalTextEncodingName("ISO-8859-8");
    return m_name == a;
}

bool TextEncoding::isNonByteBasedEncoding() const
{
    if (noExtendedTextEncodingNameUsed()) {
        return *this == UTF16LittleEndianEncoding()
            || *this == UTF16BigEndianEncoding();
    }

    return *this == UTF16LittleEndianEncoding()
        || *this == UTF16BigEndianEncoding()
        || *this == UTF32BigEndianEncoding()
        || *this == UTF32LittleEndianEncoding();
}

bool TextEncoding::isUTF7Encoding() const
{
    if (noExtendedTextEncodingNameUsed())
        return false;

    return *this == UTF7Encoding();
}

const TextEncoding& TextEncoding::closestByteBasedEquivalent() const
{
    if (isNonByteBasedEncoding())
        return UTF8Encoding();
    return *this;
}

// HTML5 specifies that UTF-8 be used in form submission when a form is
// is a part of a document in UTF-16 probably because UTF-16 is not a
// byte-based encoding and can contain 0x00. By extension, the same
// should be done for UTF-32. In case of UTF-7, it is a byte-based encoding,
// but it's fraught with problems and we'd rather steer clear of it.
const TextEncoding& TextEncoding::encodingForFormSubmission() const
{
    if (isNonByteBasedEncoding() || isUTF7Encoding())
        return UTF8Encoding();
    return *this;
}

const TextEncoding& ASCIIEncoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalASCIIEncoding = *new TextEncoding("ASCII"));
    return globalASCIIEncoding;
}

const TextEncoding& Latin1Encoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalLatin1Encoding = *new TextEncoding("latin1"));
    return globalLatin1Encoding;
}

const TextEncoding& UTF16BigEndianEncoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF16BigEndianEncoding = *new TextEncoding("UTF-16BE"));
    return globalUTF16BigEndianEncoding;
}

const TextEncoding& UTF16LittleEndianEncoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF16LittleEndianEncoding = *new TextEncoding("UTF-16LE"));
    return globalUTF16LittleEndianEncoding;
}

const TextEncoding& UTF32BigEndianEncoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF32BigEndianEncoding = *new TextEncoding("UTF-32BE"));
    return globalUTF32BigEndianEncoding;
}

const TextEncoding& UTF32LittleEndianEncoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF32LittleEndianEncoding = *new TextEncoding("UTF-32LE"));
    return globalUTF32LittleEndianEncoding;
}

const TextEncoding& UTF8Encoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalUTF8Encoding = *new TextEncoding("UTF-8"));
    ASSERT(globalUTF8Encoding.isValid());
    return globalUTF8Encoding;
}

const TextEncoding& WindowsLatin1Encoding()
{
    AtomicallyInitializedStatic(const TextEncoding&, globalWindowsLatin1Encoding = *new TextEncoding("WinLatin1"));
    return globalWindowsLatin1Encoding;
}

} // namespace WTF
<|endoftext|>


<commit_before>// easyxml.cpp - implementation of EasyXML interfaces.

#pragma warning( disable : 4786 )

#include <string.h>		// strcmp()
#include <fstream>
using namespace std;

#include "easyxml.hpp"
#include "xmlparse.h"
#include "widestring.h"

////////////////////////////////////////////////////////////////////////
// Implementation of XMLAttributes.
////////////////////////////////////////////////////////////////////////

XMLAttributes::XMLAttributes ()
{
}

XMLAttributes::~XMLAttributes ()
{
}

int XMLAttributes::findAttribute (const char * name) const
{
	int s = size();
	for (int i = 0; i < s; i++) {
		if (strcmp(name, getName(i)) == 0)
			return i;
	}
	return -1;
}

bool XMLAttributes::hasAttribute (const char * name) const
{
	return (findAttribute(name) != -1);
}

const char *XMLAttributes::getValue (const char * name) const
{
	int pos = findAttribute(name);
	if (pos >= 0)
		return getValue(pos);
	else
		return 0;
}

////////////////////////////////////////////////////////////////////////
// Implementation of XMLAttributesDefault.
////////////////////////////////////////////////////////////////////////

XMLAttributesDefault::XMLAttributesDefault ()
{
}

XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
{
	int s = atts.size();
	for (int i = 0; i < s; i++)
		addAttribute(atts.getName(i), atts.getValue(i));
}

XMLAttributesDefault::~XMLAttributesDefault ()
{
}

int XMLAttributesDefault::size () const
{
	return _atts.size() / 2;
}

const char *XMLAttributesDefault::getName (int i) const
{
	return _atts[i*2].c_str();
}

const char *XMLAttributesDefault::getValue (int i) const
{
	return _atts[i*2+1].c_str();
}

void XMLAttributesDefault::addAttribute (const char * name, const char * value)
{
	_atts.push_back(name);
	_atts.push_back(value);
}

void XMLAttributesDefault::setName (int i, const char * name)
{
	_atts[i*2] = name;
}

void XMLAttributesDefault::setValue (int i, const char * name)
{
	_atts[i*2+1] = name;
}

void XMLAttributesDefault::setValue (const char * name, const char * value)
{
	int pos = findAttribute(name);
	if (pos >= 0) {
		setName(pos, name);
		setValue(pos, value);
	} else {
		addAttribute(name, value);
	}
}

////////////////////////////////////////////////////////////////////////
// Attribute list wrapper for Expat.
////////////////////////////////////////////////////////////////////////

class ExpatAtts : public XMLAttributes
{
public:
	ExpatAtts (const char ** atts) : _atts(atts) {}

	virtual int size () const;
	virtual const char * getName (int i) const;
	virtual const char * getValue (int i) const;

private:
	const char ** _atts;
};

int ExpatAtts::size () const
{
	int s = 0;
	for (int i = 0; _atts[i] != 0; i += 2)
		s++;
	return s;
}

const char *ExpatAtts::getName (int i) const
{
	return _atts[i*2];
}

const char *ExpatAtts::getValue (int i) const
{
	return _atts[i*2+1];
}

////////////////////////////////////////////////////////////////////////
// Static callback functions for Expat.
////////////////////////////////////////////////////////////////////////

#define VISITOR (*((XMLVisitor *)userData))

static void start_element (void * userData, const char * name, const char ** atts)
{
	VISITOR.startElement(name, ExpatAtts(atts));
}

static void end_element (void * userData, const char * name)
{
	VISITOR.endElement(name);
}

static void character_data (void * userData, const char * s, int len)
{
	VISITOR.data(s, len);
}

static void processing_instruction (void * userData,
			const char * target,
			const char * data)
{
	VISITOR.pi(target, data);
}

#undef VISITOR

////////////////////////////////////////////////////////////////////////
// Implementation of XMLReader.
////////////////////////////////////////////////////////////////////////

/**
 * Read and parse the XML from an istream.
 */
void readXML (istream &input, XMLVisitor &visitor, const string &path,
			  bool progress_callback(int))
{
	XML_Parser parser = XML_ParserCreate(0);
	XML_SetUserData(parser, &visitor);
	XML_SetElementHandler(parser, start_element, end_element);
	XML_SetCharacterDataHandler(parser, character_data);
	XML_SetProcessingInstructionHandler(parser, processing_instruction);

	visitor.startXML();

	int progress = 0;
	char buf[16384];
	while (!input.eof())
	{
		// FIXME: get proper error string from system
		if (!input.good())
		{
			XML_ParserFree(parser);
			throw xh_io_exception("Problem reading file",
					xh_location(path,
					XML_GetCurrentLineNumber(parser),
					XML_GetCurrentColumnNumber(parser)),
					"XML Parser");
		}

		input.read(buf,16384);
		if (!XML_Parse(parser, buf, input.gcount(), false))
		{
			const XML_LChar *message = XML_ErrorString(XML_GetErrorCode(parser));
			int line = XML_GetCurrentLineNumber(parser);
			int col = XML_GetCurrentColumnNumber(parser);
			XML_ParserFree(parser);
			throw xh_io_exception(message,
					xh_location(path, line, col),
					"XML Parser");
		}
		if (progress_callback != NULL)
		{
			progress++;
			if (progress == 400)
				progress = 0;
			progress_callback(progress/4);
		}
	}

	// Verify end of document.
	if (!XML_Parse(parser, buf, 0, true)) {
		XML_ParserFree(parser);
		throw xh_io_exception(XML_ErrorString(XML_GetErrorCode(parser)),
				xh_location(path,
							XML_GetCurrentLineNumber(parser),
							XML_GetCurrentColumnNumber(parser)),
				"XML Parser");
	}

	XML_ParserFree(parser);
}

/**
 * Read and parse the XML from a file.
 */
void readXML (const string &path_utf8, XMLVisitor &visitor,
			  bool progress_callback(int))
{
	FILE *fp;
#if WIN32
	// For Windows we need to convert the utf-8 path to either multi-byte
	//  (which might fail in some cases) or wide characters (wchar_t).
	// The latter is better.
	widestring fn;
	fn.from_utf8(path_utf8.c_str());
	fp = _wfopen(fn.c_str(), L"rb");
#elif __DARWIN_OSX__
	// Mac OS X already likes utf-8.
	fp = fopen(path_utf8.c_str(), "rb");
#else
	// some other Unix flavor
	widestring fn;
	fn.from_utf8(path_utf8.c_str());
	fp = fopen(fn.mb_str(), "rb");
#endif
	if (!fp)
		throw xh_io_exception("Failed to open file", xh_location(path_utf8),
					"XML Parser");

	// If it is not compressed, we can get the length of the file
	int iFileLength = -1;
	if (progress_callback != NULL)
	{
		const char *path_cstr = path_utf8.c_str();

		// Not compressed if: filename does not end with "gz"
		if (strncmp(path_cstr+path_utf8.length()-2, "gz", 2))
		{
			fseek(fp, 0, SEEK_END);
			iFileLength = ftell(fp);
			rewind(fp);
		}
	}

#ifdef _MSC_VER
	int fd = _fileno(fp);
#else
	int fd = fileno(fp);
#endif
	gzFile gfp = gzdopen(fd, "rb");

	if (!gfp)
		throw xh_io_exception("Failed to open file", xh_location(path_utf8),
					"XML Parser");
	try
	{
		readCompressedXML(gfp, visitor, path_utf8, iFileLength, progress_callback);
	}
	catch (xh_io_exception &e)
	{
			gzclose(gfp);
			throw e;
	}
	catch (xh_throwable &t)
	{
			gzclose(gfp);
			throw t;
	}
	// If it gets here, it succeeded
	gzclose(gfp);
}

void readCompressedXML (gzFile fp, XMLVisitor &visitor, const string& path,
						int iFileLength, bool progress_callback(int))
{
	XML_Parser parser = XML_ParserCreate(0);
	XML_SetUserData(parser, &visitor);
	XML_SetElementHandler(parser, start_element, end_element);
	XML_SetCharacterDataHandler(parser, character_data);
	XML_SetProcessingInstructionHandler(parser, processing_instruction);

	visitor.startXML();

	const int BUFSIZE = 8192;
	int progress = 0;
	char buf[8192];
	while (!gzeof(fp))
	{
		int iCount = gzread(fp, buf, BUFSIZE);
		if (iCount > 0)
		{
			if (!XML_Parse(parser, buf, iCount, false))
			{
				const XML_LChar *message = XML_ErrorString(XML_GetErrorCode(parser));
				int line = XML_GetCurrentLineNumber(parser);
				int col = XML_GetCurrentColumnNumber(parser);
				XML_ParserFree(parser);
				throw xh_io_exception(message,
						xh_location(path, line, col),
						"XML Parser");
			}
			if (progress_callback != NULL)
			{
				if (iFileLength != -1)
				{
					// We know the length, so we can estimate total progress
					progress += iCount;
					// beware integer overflow, use doubles
					double prog = (float)progress * 99.0 / iFileLength;
					progress_callback((int) prog);
				}
				else
				{
					// Give a gradually advancing progress that wraps around
					progress++;
					if (progress == 400)
						progress = 0;
					progress_callback(progress/4);
				}
			}
		}
		else if (iCount < 0)
		{
			XML_ParserFree(parser);
			throw xh_io_exception("Problem reading file",
					xh_location(path,
					XML_GetCurrentLineNumber(parser),
					XML_GetCurrentColumnNumber(parser)),
					"XML Parser");
		}
	}

	// Verify end of document.
	if (!XML_Parse(parser, buf, 0, true))
	{
		XML_Error errcode = XML_GetErrorCode(parser);
		const XML_LChar *errstr = XML_ErrorString(errcode);
		int line = XML_GetCurrentLineNumber(parser);
		int column = XML_GetCurrentColumnNumber(parser);

		XML_ParserFree(parser);

		throw xh_io_exception(errstr,
				xh_location(path,
							line,
							column),
				"XML Parser");
	}

	XML_ParserFree(parser);
}

<commit_msg>rewind(FILE*) does not rewind the underlying file descriptor on some platforms. So added a forced lseek. Also cleaned up the usage of unitialised variables in error messages.<commit_after>// easyxml.cpp - implementation of EasyXML interfaces.

#pragma warning( disable : 4786 )

#include <string.h>		// strcmp()
#include <fstream>
using namespace std;

#include "easyxml.hpp"
#include "xmlparse.h"
#include "widestring.h"

////////////////////////////////////////////////////////////////////////
// Implementation of XMLAttributes.
////////////////////////////////////////////////////////////////////////

XMLAttributes::XMLAttributes ()
{
}

XMLAttributes::~XMLAttributes ()
{
}

int XMLAttributes::findAttribute (const char * name) const
{
	int s = size();
	for (int i = 0; i < s; i++) {
		if (strcmp(name, getName(i)) == 0)
			return i;
	}
	return -1;
}

bool XMLAttributes::hasAttribute (const char * name) const
{
	return (findAttribute(name) != -1);
}

const char *XMLAttributes::getValue (const char * name) const
{
	int pos = findAttribute(name);
	if (pos >= 0)
		return getValue(pos);
	else
		return 0;
}

////////////////////////////////////////////////////////////////////////
// Implementation of XMLAttributesDefault.
////////////////////////////////////////////////////////////////////////

XMLAttributesDefault::XMLAttributesDefault ()
{
}

XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
{
	int s = atts.size();
	for (int i = 0; i < s; i++)
		addAttribute(atts.getName(i), atts.getValue(i));
}

XMLAttributesDefault::~XMLAttributesDefault ()
{
}

int XMLAttributesDefault::size () const
{
	return _atts.size() / 2;
}

const char *XMLAttributesDefault::getName (int i) const
{
	return _atts[i*2].c_str();
}

const char *XMLAttributesDefault::getValue (int i) const
{
	return _atts[i*2+1].c_str();
}

void XMLAttributesDefault::addAttribute (const char * name, const char * value)
{
	_atts.push_back(name);
	_atts.push_back(value);
}

void XMLAttributesDefault::setName (int i, const char * name)
{
	_atts[i*2] = name;
}

void XMLAttributesDefault::setValue (int i, const char * name)
{
	_atts[i*2+1] = name;
}

void XMLAttributesDefault::setValue (const char * name, const char * value)
{
	int pos = findAttribute(name);
	if (pos >= 0) {
		setName(pos, name);
		setValue(pos, value);
	} else {
		addAttribute(name, value);
	}
}

////////////////////////////////////////////////////////////////////////
// Attribute list wrapper for Expat.
////////////////////////////////////////////////////////////////////////

class ExpatAtts : public XMLAttributes
{
public:
	ExpatAtts (const char ** atts) : _atts(atts) {}

	virtual int size () const;
	virtual const char * getName (int i) const;
	virtual const char * getValue (int i) const;

private:
	const char ** _atts;
};

int ExpatAtts::size () const
{
	int s = 0;
	for (int i = 0; _atts[i] != 0; i += 2)
		s++;
	return s;
}

const char *ExpatAtts::getName (int i) const
{
	return _atts[i*2];
}

const char *ExpatAtts::getValue (int i) const
{
	return _atts[i*2+1];
}

////////////////////////////////////////////////////////////////////////
// Static callback functions for Expat.
////////////////////////////////////////////////////////////////////////

#define VISITOR (*((XMLVisitor *)userData))

static void start_element (void * userData, const char * name, const char ** atts)
{
	VISITOR.startElement(name, ExpatAtts(atts));
}

static void end_element (void * userData, const char * name)
{
	VISITOR.endElement(name);
}

static void character_data (void * userData, const char * s, int len)
{
	VISITOR.data(s, len);
}

static void processing_instruction (void * userData,
			const char * target,
			const char * data)
{
	VISITOR.pi(target, data);
}

#undef VISITOR

////////////////////////////////////////////////////////////////////////
// Implementation of XMLReader.
////////////////////////////////////////////////////////////////////////

/**
 * Read and parse the XML from an istream.
 */
void readXML (istream &input, XMLVisitor &visitor, const string &path,
			  bool progress_callback(int))
{
	XML_Parser parser = XML_ParserCreate(0);
	XML_SetUserData(parser, &visitor);
	XML_SetElementHandler(parser, start_element, end_element);
	XML_SetCharacterDataHandler(parser, character_data);
	XML_SetProcessingInstructionHandler(parser, processing_instruction);

	visitor.startXML();

	int progress = 0;
	char buf[16384];
	while (!input.eof())
	{
		// FIXME: get proper error string from system
		if (!input.good())
		{
			int CurrentLineNumber = XML_GetCurrentLineNumber(parser);
			int CurrentColumnNumber = XML_GetCurrentColumnNumber(parser);
			XML_ParserFree(parser);
			throw xh_io_exception("Problem reading file",
					xh_location(path,
					CurrentLineNumber,
					CurrentColumnNumber),
					"XML Parser");
		}

		input.read(buf,16384);
		if (!XML_Parse(parser, buf, input.gcount(), false))
		{
			const XML_LChar *message = XML_ErrorString(XML_GetErrorCode(parser));
			int line = XML_GetCurrentLineNumber(parser);
			int col = XML_GetCurrentColumnNumber(parser);
			XML_ParserFree(parser);
			throw xh_io_exception(message,
					xh_location(path, line, col),
					"XML Parser");
		}
		if (progress_callback != NULL)
		{
			progress++;
			if (progress == 400)
				progress = 0;
			progress_callback(progress/4);
		}
	}

	// Verify end of document.
	if (!XML_Parse(parser, buf, 0, true)) {
		int CurrentLineNumber = XML_GetCurrentLineNumber(parser);
		int CurrentColumnNumber = XML_GetCurrentColumnNumber(parser);
		XML_ParserFree(parser);
		throw xh_io_exception(XML_ErrorString(XML_GetErrorCode(parser)),
				xh_location(path,
							CurrentLineNumber,
							CurrentColumnNumber),
				"XML Parser");
	}

	XML_ParserFree(parser);
}

/**
 * Read and parse the XML from a file.
 */
void readXML (const string &path_utf8, XMLVisitor &visitor,
			  bool progress_callback(int))
{
	FILE *fp;
#if WIN32
	// For Windows we need to convert the utf-8 path to either multi-byte
	//  (which might fail in some cases) or wide characters (wchar_t).
	// The latter is better.
	widestring fn;
	fn.from_utf8(path_utf8.c_str());
	fp = _wfopen(fn.c_str(), L"rb");
#elif __DARWIN_OSX__
	// Mac OS X already likes utf-8.
	fp = fopen(path_utf8.c_str(), "rb");
#else
	// some other Unix flavor
	widestring fn;
	fn.from_utf8(path_utf8.c_str());
	fp = fopen(fn.mb_str(), "rb");
#endif
	if (!fp)
		throw xh_io_exception("Failed to open file", xh_location(path_utf8),
					"XML Parser");

	// If it is not compressed, we can get the length of the file
	int iFileLength = -1;
	if (progress_callback != NULL)
	{
		const char *path_cstr = path_utf8.c_str();

		// Not compressed if: filename does not end with "gz"
		if (strncmp(path_cstr+path_utf8.length()-2, "gz", 2))
		{
			fseek(fp, 0, SEEK_END);
			iFileLength = ftell(fp);
		}
	}

#ifdef _MSC_VER
	int fd = _fileno(fp);
#else
	int fd = fileno(fp);
#endif

	// Ensure that underlying fd isd rewound
	lseek(fd, 0, SEEK_SET);

	gzFile gfp = gzdopen(fd, "rb");

	if (!gfp)
		throw xh_io_exception("Failed to open file", xh_location(path_utf8),
					"XML Parser");
	try
	{
		readCompressedXML(gfp, visitor, path_utf8, iFileLength, progress_callback);
	}
	catch (xh_io_exception &e)
	{
			gzclose(gfp);
			throw e;
	}
	catch (xh_throwable &t)
	{
			gzclose(gfp);
			throw t;
	}
	// If it gets here, it succeeded
	gzclose(gfp);
}

void readCompressedXML (gzFile fp, XMLVisitor &visitor, const string& path,
						int iFileLength, bool progress_callback(int))
{
	XML_Parser parser = XML_ParserCreate(0);
	XML_SetUserData(parser, &visitor);
	XML_SetElementHandler(parser, start_element, end_element);
	XML_SetCharacterDataHandler(parser, character_data);
	XML_SetProcessingInstructionHandler(parser, processing_instruction);

	visitor.startXML();

	const int BUFSIZE = 8192;
	int progress = 0;
	char buf[8192];
	while (!gzeof(fp))
	{
		int iError;
		gzerror(fp, &iError);
		int iCount = gzread(fp, buf, BUFSIZE);
		gzerror(fp, &iError);
		if (iCount > 0)
		{
			if (!XML_Parse(parser, buf, iCount, false))
			{
				const XML_LChar *message = XML_ErrorString(XML_GetErrorCode(parser));
				int line = XML_GetCurrentLineNumber(parser);
				int col = XML_GetCurrentColumnNumber(parser);
				XML_ParserFree(parser);
				throw xh_io_exception(message,
						xh_location(path, line, col),
						"XML Parser");
			}
			if (progress_callback != NULL)
			{
				if (iFileLength != -1)
				{
					// We know the length, so we can estimate total progress
					progress += iCount;
					// beware integer overflow, use doubles
					double prog = (float)progress * 99.0 / iFileLength;
					progress_callback((int) prog);
				}
				else
				{
					// Give a gradually advancing progress that wraps around
					progress++;
					if (progress == 400)
						progress = 0;
					progress_callback(progress/4);
				}
			}
		}
		else if (iCount < 0)
		{
			int CurrentLineNumber = XML_GetCurrentLineNumber(parser);
			int CurrentColumnNumber = XML_GetCurrentColumnNumber(parser);
			XML_ParserFree(parser);
			throw xh_io_exception("Problem reading file",
					xh_location(path,
					CurrentLineNumber,
					CurrentColumnNumber),
					"XML Parser");
		}
	}

	// Verify end of document.
	if (!XML_Parse(parser, buf, 0, true))
	{
		XML_Error errcode = XML_GetErrorCode(parser);
		const XML_LChar *errstr = XML_ErrorString(errcode);
		int line = XML_GetCurrentLineNumber(parser);
		int column = XML_GetCurrentColumnNumber(parser);

		XML_ParserFree(parser);

		throw xh_io_exception(errstr,
				xh_location(path,
							line,
							column),
				"XML Parser");
	}

	XML_ParserFree(parser);
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
 * Copyright (C) 2006 George Stiakos <staikos@kde.org>
 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2008 Holger Hans Peter Freyther
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "Cursor.h"
#include "Font.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "RenderObject.h"
#include "ScrollView.h"
#include "Widget.h"
#include "NotImplemented.h"

#include "qwebframe.h"
#include "qwebframe_p.h"
#include "qwebpage.h"

#include <QCoreApplication>
#include <QPainter>
#include <QPaintEngine>

#include <QDebug>

namespace WebCore {

Widget::Widget(QWidget* widget)
{
    init(widget);
}

Widget::~Widget()
{
    Q_ASSERT(!parent());
}

IntRect Widget::frameRect() const
{
    return m_frame;
}

void Widget::setFrameRect(const IntRect& rect)
{
    if (platformWidget())
        platformWidget()->setGeometry(convertToContainingWindow(IntRect(0, 0, rect.width(), rect.height())));
    m_frame = rect;
}

void Widget::setFocus()
{
}

void Widget::setCursor(const Cursor& cursor)
{
#ifndef QT_NO_CURSOR
    if (QWidget* widget = containingWindow())
        QCoreApplication::postEvent(widget, new SetCursorEvent(cursor.impl()));
#endif
}

void Widget::show()
{
    if (platformWidget())
        platformWidget()->show();
}

void Widget::hide()
{
    if (platformWidget())
        platformWidget()->hide();
}

void Widget::paint(GraphicsContext *, const IntRect &rect)
{
}

void Widget::setIsSelected(bool)
{
    notImplemented();
}

}

// vim: ts=4 sw=4 et
<commit_msg>Fix Qt build bustage.<commit_after>/*
 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
 * Copyright (C) 2006 George Stiakos <staikos@kde.org>
 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2008 Holger Hans Peter Freyther
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "Cursor.h"
#include "Font.h"
#include "GraphicsContext.h"
#include "HostWindow.h"
#include "IntRect.h"
#include "ScrollView.h"
#include "Widget.h"
#include "NotImplemented.h"

#include "qwebframe.h"
#include "qwebframe_p.h"
#include "qwebpage.h"

#include <QCoreApplication>
#include <QPainter>
#include <QPaintEngine>

#include <QDebug>

namespace WebCore {

Widget::Widget(QWidget* widget)
{
    init(widget);
}

Widget::~Widget()
{
    Q_ASSERT(!parent());
}

IntRect Widget::frameRect() const
{
    return m_frame;
}

void Widget::setFrameRect(const IntRect& rect)
{
    if (platformWidget())
        platformWidget()->setGeometry(convertToContainingWindow(IntRect(0, 0, rect.width(), rect.height())));
    m_frame = rect;
}

void Widget::setFocus()
{
}

void Widget::setCursor(const Cursor& cursor)
{
#ifndef QT_NO_CURSOR
    if (QWidget* widget = root()->hostWindow()->platformWindow())
        QCoreApplication::postEvent(widget, new SetCursorEvent(cursor.impl()));
#endif
}

void Widget::show()
{
    if (platformWidget())
        platformWidget()->show();
}

void Widget::hide()
{
    if (platformWidget())
        platformWidget()->hide();
}

void Widget::paint(GraphicsContext *, const IntRect &rect)
{
}

void Widget::setIsSelected(bool)
{
    notImplemented();
}

}

// vim: ts=4 sw=4 et
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: VPolarCoordinateSystem.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 01:40:50 $
 *
 *  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 _CHART2_VPOLAR_COORDINATESYSTEM_HXX
#define _CHART2_VPOLAR_COORDINATESYSTEM_HXX

#include "VCoordinateSystem.hxx"

//.............................................................................
namespace chart
{
//.............................................................................

//-----------------------------------------------------------------------------
/**
*/
class VPolarCoordinateSystem : public VCoordinateSystem
{
public:
    VPolarCoordinateSystem( const ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XBoundedCoordinateSystem >& xCooSys );
    virtual ~VPolarCoordinateSystem();

    virtual void createGridShapes();
    virtual void createAxesShapes( const ::com::sun::star::awt::Size& rReferenceSize, NumberFormatterWrapper* pNumberFormatterWrapper );

private:
    VPolarCoordinateSystem();
};

//.............................................................................
} //namespace chart
//.............................................................................
#endif
<commit_msg>INTEGRATION: CWS chart2mst3 (1.2.4); FILE MERGED 2006/11/09 15:32:56 iha 1.2.4.7: #i16280# better performance for charts with many data (bar,column,line,area,xy,net charts) 2006/08/25 17:16:48 iha 1.2.4.6: text- and diagram-size dependent auto main step width 2006/08/23 17:07:27 iha 1.2.4.5: enable axis to estimate the maximum automatic MainIncrementCount, reduce count to 2 for net charts 2006/08/10 16:02:24 iha 1.2.4.4: Axis Label Layout - Font&Diagram Size 2005/10/13 17:39:12 iha 1.2.4.3: renamed BoundedCoordinateSystem to CoordinateSystem 2005/10/07 12:19:24 bm 1.2.4.2: RESYNC: (1.2-1.3); FILE MERGED 2005/06/07 16:03:28 iha 1.2.4.1: use numberformatter from model<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: VPolarCoordinateSystem.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-22 19:13:16 $
 *
 *  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 _CHART2_VPOLAR_COORDINATESYSTEM_HXX
#define _CHART2_VPOLAR_COORDINATESYSTEM_HXX

#include "VCoordinateSystem.hxx"

//.............................................................................
namespace chart
{
//.............................................................................

//-----------------------------------------------------------------------------
/**
*/
class VPolarCoordinateSystem : public VCoordinateSystem
{
public:
    VPolarCoordinateSystem( const ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XCoordinateSystem >& xCooSys );
    virtual ~VPolarCoordinateSystem();

    //better performance for big data
    virtual ::com::sun::star::uno::Sequence< sal_Int32 > getCoordinateSystemResolution( const ::com::sun::star::awt::Size& rPageSize
                                    , const ::com::sun::star::awt::Size& rPageResolution );

    virtual void createVAxisList(
            const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xNumberFormatsSupplier
            , const ::com::sun::star::awt::Size& rFontReferenceSize
            , const ::com::sun::star::awt::Rectangle& rMaximumSpaceForLabels );

    virtual void initVAxisInList();
    virtual void updateScalesAndIncrementsOnAxes();

    virtual void createGridShapes();

private:
    VPolarCoordinateSystem();
};

//.............................................................................
} //namespace chart
//.............................................................................
#endif
<|endoftext|>


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

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

#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::ImageLoader

// A RefCounted class for loading images on the File thread and reporting back
// on the UI thread.
class ImageLoadingTracker::ImageLoader
    : public base::RefCountedThreadSafe<ImageLoader> {
 public:
  explicit ImageLoader(ImageLoadingTracker* tracker)
      : tracker_(tracker) {
    CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_));
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  }

  // Lets this class know that the tracker is no longer interested in the
  // results.
  void StopTracking() {
    tracker_ = NULL;
  }

  // Instructs the loader to load a task on the File thread.
  void LoadImage(const ExtensionResource& resource,
                 const gfx::Size& max_size,
                 int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
    ChromeThread::PostTask(
        ChromeThread::FILE, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::LoadOnFileThread, resource,
                          max_size, id));
  }

  void LoadOnFileThread(ExtensionResource resource,
                        const gfx::Size& max_size,
                        int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    // Read the file from disk.
    std::string file_contents;
    FilePath path = resource.GetFilePath();
    if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
      ReportBack(NULL, resource, id);
      return;
    }

    // Decode the image using WebKit's image decoder.
    const unsigned char* data =
        reinterpret_cast<const unsigned char*>(file_contents.data());
    webkit_glue::ImageDecoder decoder;
    scoped_ptr<SkBitmap> decoded(new SkBitmap());
    *decoded = decoder.Decode(data, file_contents.length());
    if (decoded->empty()) {
      ReportBack(NULL, resource, id);
      return;  // Unable to decode.
    }

    if (decoded->width() > max_size.width() ||
        decoded->height() > max_size.height()) {
      // The bitmap is too big, re-sample.
      *decoded = skia::ImageOperations::Resize(
          *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
          max_size.width(), max_size.height());
    }

    ReportBack(decoded.release(), resource, id);
  }

  void ReportBack(SkBitmap* image, const ExtensionResource& resource,
                  int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    ChromeThread::PostTask(
        callback_thread_id_, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::ReportOnUIThread,
                          image, resource, id));
  }

  void ReportOnUIThread(SkBitmap* image, ExtensionResource resource,
                        int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));

    if (tracker_)
      tracker_->OnImageLoaded(image, resource, id);

    delete image;
  }

 private:
  // The tracker we are loading the image for. If NULL, it means the tracker is
  // no longer interested in the reply.
  ImageLoadingTracker* tracker_;

  // The thread that we need to call back on to report that we are done.
  ChromeThread::ID callback_thread_id_;

  DISALLOW_COPY_AND_ASSIGN(ImageLoader);
};

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker

ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
    : observer_(observer),
      next_id_(0) {
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 NotificationService::AllSources());
}

ImageLoadingTracker::~ImageLoadingTracker() {
  // The loader is created lazily and is NULL if the tracker is destroyed before
  // any valid image load tasks have been posted.
  if (loader_)
    loader_->StopTracking();
}

void ImageLoadingTracker::LoadImage(Extension* extension,
                                    const ExtensionResource& resource,
                                    const gfx::Size& max_size,
                                    CacheParam cache) {
  DCHECK(extension->path() == resource.extension_root());

  // If we don't have a path we don't need to do any further work, just respond
  // back.
  int id = next_id_++;
  if (resource.relative_path().empty()) {
    OnImageLoaded(NULL, resource, id);
    return;
  }

  // See if the extension has the image already.
  if (extension->HasCachedImage(resource)) {
    SkBitmap image = extension->GetCachedImage(resource);
    OnImageLoaded(&image, resource, id);
    return;
  }

  if (cache == CACHE) {
    load_map_[id] = extension;
  }

  // Instruct the ImageLoader to load this on the File thread. LoadImage does
  // not block.
  if (!loader_)
    loader_ = new ImageLoader(this);
  loader_->LoadImage(resource, max_size, id);
}

void ImageLoadingTracker::OnImageLoaded(
    SkBitmap* image,
    const ExtensionResource& resource,
    int id) {
  LoadMap::iterator i = load_map_.find(id);
  if (i != load_map_.end()) {
    i->second->SetCachedImage(resource, image ? *image : SkBitmap());
    load_map_.erase(i);
  }

  observer_->OnImageLoaded(image, resource, id);
}

void ImageLoadingTracker::Observe(NotificationType type,
                                  const NotificationSource& source,
                                  const NotificationDetails& details) {
  DCHECK(type == NotificationType::EXTENSION_UNLOADED ||
         type == NotificationType::EXTENSION_UNLOADED_DISABLED);

  Extension* extension = Details<Extension>(details).ptr();

  // Remove all entries in the load_map_ referencing the extension. This ensures
  // we don't attempt to cache the image when the load completes.
  for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) {
    if (i->second == extension) {
      load_map_.erase(i++);
    } else {
      ++i;
    }
  }
}
<commit_msg>Fixes bug in ImageLoadintTracker where it would incorrectly hit a DCHECK if the extension doesn't have an image for a particular resource.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::ImageLoader

// A RefCounted class for loading images on the File thread and reporting back
// on the UI thread.
class ImageLoadingTracker::ImageLoader
    : public base::RefCountedThreadSafe<ImageLoader> {
 public:
  explicit ImageLoader(ImageLoadingTracker* tracker)
      : tracker_(tracker) {
    CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_));
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  }

  // Lets this class know that the tracker is no longer interested in the
  // results.
  void StopTracking() {
    tracker_ = NULL;
  }

  // Instructs the loader to load a task on the File thread.
  void LoadImage(const ExtensionResource& resource,
                 const gfx::Size& max_size,
                 int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
    ChromeThread::PostTask(
        ChromeThread::FILE, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::LoadOnFileThread, resource,
                          max_size, id));
  }

  void LoadOnFileThread(ExtensionResource resource,
                        const gfx::Size& max_size,
                        int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    // Read the file from disk.
    std::string file_contents;
    FilePath path = resource.GetFilePath();
    if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
      ReportBack(NULL, resource, id);
      return;
    }

    // Decode the image using WebKit's image decoder.
    const unsigned char* data =
        reinterpret_cast<const unsigned char*>(file_contents.data());
    webkit_glue::ImageDecoder decoder;
    scoped_ptr<SkBitmap> decoded(new SkBitmap());
    *decoded = decoder.Decode(data, file_contents.length());
    if (decoded->empty()) {
      ReportBack(NULL, resource, id);
      return;  // Unable to decode.
    }

    if (decoded->width() > max_size.width() ||
        decoded->height() > max_size.height()) {
      // The bitmap is too big, re-sample.
      *decoded = skia::ImageOperations::Resize(
          *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
          max_size.width(), max_size.height());
    }

    ReportBack(decoded.release(), resource, id);
  }

  void ReportBack(SkBitmap* image, const ExtensionResource& resource,
                  int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    ChromeThread::PostTask(
        callback_thread_id_, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::ReportOnUIThread,
                          image, resource, id));
  }

  void ReportOnUIThread(SkBitmap* image, ExtensionResource resource,
                        int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));

    if (tracker_)
      tracker_->OnImageLoaded(image, resource, id);

    delete image;
  }

 private:
  // The tracker we are loading the image for. If NULL, it means the tracker is
  // no longer interested in the reply.
  ImageLoadingTracker* tracker_;

  // The thread that we need to call back on to report that we are done.
  ChromeThread::ID callback_thread_id_;

  DISALLOW_COPY_AND_ASSIGN(ImageLoader);
};

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker

ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
    : observer_(observer),
      next_id_(0) {
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 NotificationService::AllSources());
}

ImageLoadingTracker::~ImageLoadingTracker() {
  // The loader is created lazily and is NULL if the tracker is destroyed before
  // any valid image load tasks have been posted.
  if (loader_)
    loader_->StopTracking();
}

void ImageLoadingTracker::LoadImage(Extension* extension,
                                    const ExtensionResource& resource,
                                    const gfx::Size& max_size,
                                    CacheParam cache) {
  // If we don't have a path we don't need to do any further work, just respond
  // back.
  int id = next_id_++;
  if (resource.relative_path().empty()) {
    OnImageLoaded(NULL, resource, id);
    return;
  }

  DCHECK(extension->path() == resource.extension_root());

  // See if the extension has the image already.
  if (extension->HasCachedImage(resource)) {
    SkBitmap image = extension->GetCachedImage(resource);
    OnImageLoaded(&image, resource, id);
    return;
  }

  if (cache == CACHE) {
    load_map_[id] = extension;
  }

  // Instruct the ImageLoader to load this on the File thread. LoadImage does
  // not block.
  if (!loader_)
    loader_ = new ImageLoader(this);
  loader_->LoadImage(resource, max_size, id);
}

void ImageLoadingTracker::OnImageLoaded(
    SkBitmap* image,
    const ExtensionResource& resource,
    int id) {
  LoadMap::iterator i = load_map_.find(id);
  if (i != load_map_.end()) {
    i->second->SetCachedImage(resource, image ? *image : SkBitmap());
    load_map_.erase(i);
  }

  observer_->OnImageLoaded(image, resource, id);
}

void ImageLoadingTracker::Observe(NotificationType type,
                                  const NotificationSource& source,
                                  const NotificationDetails& details) {
  DCHECK(type == NotificationType::EXTENSION_UNLOADED ||
         type == NotificationType::EXTENSION_UNLOADED_DISABLED);

  Extension* extension = Details<Extension>(details).ptr();

  // Remove all entries in the load_map_ referencing the extension. This ensures
  // we don't attempt to cache the image when the load completes.
  for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) {
    if (i->second == extension) {
      load_map_.erase(i++);
    } else {
      ++i;
    }
  }
}
<|endoftext|>


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

#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"

#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"

DEFINE_WEB_CONTENTS_USER_DATA_KEY(BookmarkTabHelper)

namespace {

bool CanShowBookmarkBar(content::WebUI* ui) {
  if (!ui)
    return false;
  NewTabUI* new_tab = NewTabUI::FromWebUIController(ui->GetController());
  return new_tab && new_tab->CanShowBookmarkBar();
}

}  // namespace

BookmarkTabHelper::BookmarkTabHelper(content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents),
      is_starred_(false),
      bookmark_model_(NULL),
      delegate_(NULL),
      bookmark_drag_(NULL) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  bookmark_model_= BookmarkModelFactory::GetForProfile(profile);
  if (bookmark_model_)
    bookmark_model_->AddObserver(this);
}

BookmarkTabHelper::~BookmarkTabHelper() {
  if (bookmark_model_)
    bookmark_model_->RemoveObserver(this);
}

bool BookmarkTabHelper::ShouldShowBookmarkBar() {
  if (web_contents()->ShowingInterstitialPage())
    return false;

  // See WebContents::GetWebUIForCurrentState() comment for more info. This case
  // is very similar, but for non-first loads, we want to use the committed
  // entry. This is so the bookmarks bar disappears at the same time the page
  // does.
  if (web_contents()->GetController().GetLastCommittedEntry()) {
    // Not the first load, always use the committed Web UI.
    return CanShowBookmarkBar(web_contents()->GetCommittedWebUI());
  }

  // When it's the first load, we know either the pending one or the committed
  // one will have the Web UI in it (see GetWebUIForCurrentState), and only one
  // of them will be valid, so we can just check both.
  return CanShowBookmarkBar(web_contents()->GetWebUI());
}

void BookmarkTabHelper::DidNavigateMainFrame(
    const content::LoadCommittedDetails& /*details*/,
    const content::FrameNavigateParams& /*params*/) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::SetBookmarkDragDelegate(
    BookmarkTabHelper::BookmarkDrag* bookmark_drag) {
  bookmark_drag_ = bookmark_drag;
}

BookmarkTabHelper::BookmarkDrag*
    BookmarkTabHelper::GetBookmarkDragDelegate() {
  return bookmark_drag_;
}

void BookmarkTabHelper::UpdateStarredStateForCurrentURL() {
  const bool old_state = is_starred_;
  is_starred_ = (bookmark_model_ &&
                 bookmark_model_->IsBookmarked(web_contents()->GetURL()));

  if (is_starred_ != old_state && delegate())
    delegate()->URLStarredChanged(web_contents(), is_starred_);
}

void BookmarkTabHelper::BookmarkModelChanged() {
}

void BookmarkTabHelper::Loaded(BookmarkModel* model, bool ids_reassigned) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeAdded(BookmarkModel* model,
                                          const BookmarkNode* parent,
                                          int index) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeRemoved(BookmarkModel* model,
                                            const BookmarkNode* parent,
                                            int old_index,
                                            const BookmarkNode* node) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeChanged(BookmarkModel* model,
                                            const BookmarkNode* node) {
  UpdateStarredStateForCurrentURL();
}
<commit_msg>bookmarks: Remove some unused header includes from bookmark_tab_helper.cc<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"

#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper_delegate.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "content/public/browser/web_contents.h"

DEFINE_WEB_CONTENTS_USER_DATA_KEY(BookmarkTabHelper)

namespace {

bool CanShowBookmarkBar(content::WebUI* ui) {
  if (!ui)
    return false;
  NewTabUI* new_tab = NewTabUI::FromWebUIController(ui->GetController());
  return new_tab && new_tab->CanShowBookmarkBar();
}

}  // namespace

BookmarkTabHelper::BookmarkTabHelper(content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents),
      is_starred_(false),
      bookmark_model_(NULL),
      delegate_(NULL),
      bookmark_drag_(NULL) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  bookmark_model_= BookmarkModelFactory::GetForProfile(profile);
  if (bookmark_model_)
    bookmark_model_->AddObserver(this);
}

BookmarkTabHelper::~BookmarkTabHelper() {
  if (bookmark_model_)
    bookmark_model_->RemoveObserver(this);
}

bool BookmarkTabHelper::ShouldShowBookmarkBar() {
  if (web_contents()->ShowingInterstitialPage())
    return false;

  // See WebContents::GetWebUIForCurrentState() comment for more info. This case
  // is very similar, but for non-first loads, we want to use the committed
  // entry. This is so the bookmarks bar disappears at the same time the page
  // does.
  if (web_contents()->GetController().GetLastCommittedEntry()) {
    // Not the first load, always use the committed Web UI.
    return CanShowBookmarkBar(web_contents()->GetCommittedWebUI());
  }

  // When it's the first load, we know either the pending one or the committed
  // one will have the Web UI in it (see GetWebUIForCurrentState), and only one
  // of them will be valid, so we can just check both.
  return CanShowBookmarkBar(web_contents()->GetWebUI());
}

void BookmarkTabHelper::DidNavigateMainFrame(
    const content::LoadCommittedDetails& /*details*/,
    const content::FrameNavigateParams& /*params*/) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::SetBookmarkDragDelegate(
    BookmarkTabHelper::BookmarkDrag* bookmark_drag) {
  bookmark_drag_ = bookmark_drag;
}

BookmarkTabHelper::BookmarkDrag*
    BookmarkTabHelper::GetBookmarkDragDelegate() {
  return bookmark_drag_;
}

void BookmarkTabHelper::UpdateStarredStateForCurrentURL() {
  const bool old_state = is_starred_;
  is_starred_ = (bookmark_model_ &&
                 bookmark_model_->IsBookmarked(web_contents()->GetURL()));

  if (is_starred_ != old_state && delegate())
    delegate()->URLStarredChanged(web_contents(), is_starred_);
}

void BookmarkTabHelper::BookmarkModelChanged() {
}

void BookmarkTabHelper::Loaded(BookmarkModel* model, bool ids_reassigned) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeAdded(BookmarkModel* model,
                                          const BookmarkNode* parent,
                                          int index) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeRemoved(BookmarkModel* model,
                                            const BookmarkNode* parent,
                                            int old_index,
                                            const BookmarkNode* node) {
  UpdateStarredStateForCurrentURL();
}

void BookmarkTabHelper::BookmarkNodeChanged(BookmarkModel* model,
                                            const BookmarkNode* node) {
  UpdateStarredStateForCurrentURL();
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2010, Intel Corporation. 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/ui/meegotouch/bookmark_bubble_qt.h"

#include "ui/base/l10n/l10n_util.h"
#include "base/basictypes.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_editor.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/profiles/profile.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "content/common/notification_service.h"
#include "grit/generated_resources.h"
#include <QTextCodec>
#include <QString>
#include <QObject>
#include <QDeclarativeEngine>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QDeclarativeItem>
#include <QGraphicsLineItem>
#include <QVariant>
#include <QAbstractListModel>
#include <QList>

namespace {

// Padding between content and edge of info bubble.
const int kContentBorder = 7;

}  // namespace
class BookmarkBubbleQtImpl : public QObject
{
  Q_OBJECT
  public:
    BookmarkBubbleQtImpl(BookmarkBubbleQt* bubble):
        QObject(NULL),
        bubble_(bubble)
    {
    }
    void PopupAt(int x, int y)
    {
       emit popupAt(x, y);
    }
  public slots:
    void doneButtonClicked()
    {
       bubble_->OnDoneClicked();
       emit close();
    }

    void removeButtonClicked()
    {
       bubble_->OnRemoveClicked();
       emit close();
    }

    void folderSelectedIndex(int index)
    {
       bubble_->SetFolderIndex(index);
    }

    void setTitle(QString title)
    {
       bubble_->SetTitle(title);
    }
  Q_SIGNALS:
    void popupAt(int x, int y);
    void close();
  private:
    BookmarkBubbleQt* bubble_;
};
/*void BookmarkBubbleQt::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                          bool closed_by_escape) {
  if (closed_by_escape) {
    remove_bookmark_ = newly_bookmarked_;
    apply_edits_ = false;
  }

  NotificationService::current()->Notify(
      NotificationType::BOOKMARK_BUBBLE_HIDDEN,
      Source<Profile>(profile_->GetOriginalProfile()),
      NotificationService::NoDetails());
}*/

void BookmarkBubbleQt::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {

}

BookmarkBubbleQt::BookmarkBubbleQt( BrowserWindowQt* window,
                                    Browser* browser,
                                     Profile* profile)
    : browser_(browser),
      profile_(profile),
      window_(window){
  impl_ = new BookmarkBubbleQtImpl(this);
  QDeclarativeView *view = window_->DeclarativeView();
  QDeclarativeContext *context = view->rootContext();
  context->setContextProperty("bookmarkBubbleObject", impl_);

}

BookmarkBubbleQt::BookmarkBubbleQt( BrowserWindowQt* window,
                                    Browser* browser,
                                     Profile* profile,
                                     const GURL& url,
                                     bool newly_bookmarked)
    : url_(url),
      browser_(browser),
      profile_(profile),
      window_(window),
      newly_bookmarked_(newly_bookmarked),
      apply_edits_(true),
      remove_bookmark_(false){

  impl_ = new BookmarkBubbleQtImpl(this);
  InitFolderComboModel();

  QDeclarativeView *view = window_->DeclarativeView();
  QDeclarativeContext *context = view->rootContext();
  context->setContextProperty("bookmarkBubbleObject", impl_);

  QString q_title;
  if (newly_bookmarked) {
    q_title = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED).c_str());
  } else {
    q_title = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK).c_str());
  }
  context->setContextProperty("bubbleTitle", q_title);

  QString q_name = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_TITLE_TEXT).c_str());
  context->setContextProperty("bubbleName", q_name);
  QString q_folder = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_FOLDER_TEXT).c_str());
  context->setContextProperty("bubbleFolder", q_folder);
  QString q_done = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_DONE).c_str());
  context->setContextProperty("bubbleDone", q_done);
  QString q_remove = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK).c_str());
  context->setContextProperty("bubbleRemove", q_remove);

//  context->setContextProperty("bubbleModel", impl_);
  context->setContextProperty("bubbleFolderModel", QVariant::fromValue(folderList_));

  BookmarkModel* model = profile_->GetBookmarkModel();
  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
  const std::string& title = UTF16ToUTF8(node->GetTitle());
  QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
  QString q_node_title = QString::fromStdString(title);
  context->setContextProperty("bubbleNameInput", q_node_title);

  const BookmarkNode* parent = node->parent();
  const std::string& folder = UTF16ToUTF8(parent->GetTitle());
  QString q_node_folder = QString::fromStdString(folder);
  context->setContextProperty("bubbleFolderInput", q_node_folder);
}

BookmarkBubbleQt::~BookmarkBubbleQt() {
  delete impl_;
}

void BookmarkBubbleQt::Apply() {
  if (apply_edits_) {
    ApplyEdits();
  } else if (remove_bookmark_){
    BookmarkModel* model = profile_->GetBookmarkModel();
    const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
    if (node)
      model->Remove(node->parent(), node->parent()->GetIndexOf(node));
  }
}

void BookmarkBubbleQt::OnRemoveClicked() {
//  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"),
//                            profile_);

  apply_edits_ = false;
  remove_bookmark_ = true;
  Apply();
}

void BookmarkBubbleQt::ApplyEdits() {
  // Set this to make sure we don't attempt to apply edits again.
  apply_edits_ = false;

  BookmarkModel* model = profile_->GetBookmarkModel();
  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
  if (node) {
    const string16 new_title = UTF8ToUTF16(name_.toUtf8().data());
    if (new_title != node->GetTitle()) {
      model->SetTitle(node, new_title);
      UserMetrics::RecordAction(
          UserMetricsAction("BookmarkBubble_ChangeTitleInBubble"),
          profile_);
    }

    // Last index means 'Create Application Bookmark...'
    if (folder_index_ < folder_combo_model_->GetItemCount() - 1) {
      const BookmarkNode* new_parent =
               folder_combo_model_->GetNodeAt(folder_index_);
      if (new_parent != node->parent()) {
        UserMetrics::RecordAction(
            UserMetricsAction("BookmarkBubble_ChangeParent"), profile_);
        model->Move(node, new_parent, new_parent->child_count());
      }
    }

    if (folder_index_ == folder_combo_model_->GetItemCount() - 1) {
       //TODO ./brower/browser.cc RegisterAppPrefs, ConvertContentsToApplication
      model->Remove(node->parent(), node->parent()->GetIndexOf(node));
      TabContents* current_tab_contents =
                         browser_->tabstrip_model()->GetSelectedTabContents()->tab_contents();

       // Prepare data
      web_app::GetShortcutInfoForTab(current_tab_contents, &shortcut_info_);
      shortcut_info_.create_on_desktop = true;
      shortcut_info_.create_in_quick_launch_bar = false;
      shortcut_info_.create_in_applications_menu = false;

      web_app::CreateShortcut(current_tab_contents->profile()->GetPath(),
                          shortcut_info_,
                          NULL);

    //  current_tab_contents->SetAppIcon(shortcut_info_.favicon);
   //   if (current_tab_contents->delegate())
   //      current_tab_contents->delegate()->ConvertContentsToApplication(current_tab_contents);

    }
  }
}

std::string BookmarkBubbleQt::GetTitle() {
  BookmarkModel* bookmark_model= profile_->GetBookmarkModel();
  const BookmarkNode* node =
      bookmark_model->GetMostRecentlyAddedNodeForURL(url_);
  if (!node) {
    NOTREACHED();
    return std::string();
  }

  return UTF16ToUTF8(node->GetTitle());
}

void BookmarkBubbleQt::OnDoneClicked() {
  apply_edits_ = true;
  remove_bookmark_ = false;
  Apply();
}

void BookmarkBubbleQt::InitFolderComboModel() {
  folder_combo_model_.reset(new RecentlyUsedFoldersComboModel(
      profile_->GetBookmarkModel(),
      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_)));

  for (int index = 0; index < folder_combo_model_->GetItemCount(); index ++) {
     QString folderName =
           QString::fromStdString(UTF16ToUTF8(folder_combo_model_->GetItemAt(index)));
     folderList_.append(folderName);
  }
}

// Displays the bubble at the given coords. |point| is intentionally not const.
void BookmarkBubbleQt::PopupAt(gfx::Point point)
{
  impl_->PopupAt(point.x(), point.y());
}

#include "moc_bookmark_bubble_qt.cc"
<commit_msg>Bug[5666]Saving a bookmark to "Other bookmarks" will remove that bookmark on the bookmark bar<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2010, Intel Corporation. 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/ui/meegotouch/bookmark_bubble_qt.h"

#include "ui/base/l10n/l10n_util.h"
#include "base/basictypes.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_editor.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/bookmarks/recently_used_folders_combo_model.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/profiles/profile.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "content/common/notification_service.h"
#include "grit/generated_resources.h"
#include <QTextCodec>
#include <QString>
#include <QObject>
#include <QDeclarativeEngine>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QDeclarativeItem>
#include <QGraphicsLineItem>
#include <QVariant>
#include <QAbstractListModel>
#include <QList>

namespace {

// Padding between content and edge of info bubble.
const int kContentBorder = 7;

}  // namespace
class BookmarkBubbleQtImpl : public QObject
{
  Q_OBJECT
  public:
    BookmarkBubbleQtImpl(BookmarkBubbleQt* bubble):
        QObject(NULL),
        bubble_(bubble)
    {
    }
    void PopupAt(int x, int y)
    {
       emit popupAt(x, y);
    }
  public slots:
    void doneButtonClicked()
    {
       bubble_->OnDoneClicked();
       emit close();
    }

    void removeButtonClicked()
    {
       bubble_->OnRemoveClicked();
       emit close();
    }

    void folderSelectedIndex(int index)
    {
       bubble_->SetFolderIndex(index);
    }

    void setTitle(QString title)
    {
       bubble_->SetTitle(title);
    }
  Q_SIGNALS:
    void popupAt(int x, int y);
    void close();
  private:
    BookmarkBubbleQt* bubble_;
};
/*void BookmarkBubbleQt::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                          bool closed_by_escape) {
  if (closed_by_escape) {
    remove_bookmark_ = newly_bookmarked_;
    apply_edits_ = false;
  }

  NotificationService::current()->Notify(
      NotificationType::BOOKMARK_BUBBLE_HIDDEN,
      Source<Profile>(profile_->GetOriginalProfile()),
      NotificationService::NoDetails());
}*/

void BookmarkBubbleQt::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {

}

BookmarkBubbleQt::BookmarkBubbleQt( BrowserWindowQt* window,
                                    Browser* browser,
                                     Profile* profile)
    : browser_(browser),
      profile_(profile),
      window_(window){
  impl_ = new BookmarkBubbleQtImpl(this);
  QDeclarativeView *view = window_->DeclarativeView();
  QDeclarativeContext *context = view->rootContext();
  context->setContextProperty("bookmarkBubbleObject", impl_);

}

BookmarkBubbleQt::BookmarkBubbleQt( BrowserWindowQt* window,
                                    Browser* browser,
                                     Profile* profile,
                                     const GURL& url,
                                     bool already_bookmarked)
    : url_(url),
      browser_(browser),
      profile_(profile),
      window_(window),
      newly_bookmarked_(!already_bookmarked),
      apply_edits_(true),
      remove_bookmark_(false){

  impl_ = new BookmarkBubbleQtImpl(this);
  InitFolderComboModel();

  QDeclarativeView *view = window_->DeclarativeView();
  QDeclarativeContext *context = view->rootContext();
  context->setContextProperty("bookmarkBubbleObject", impl_);

  QString q_title;
  if (newly_bookmarked_) {
    q_title = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED).c_str());
  } else {
    q_title = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK).c_str());
  }
  context->setContextProperty("bubbleTitle", q_title);

  QString q_name = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_TITLE_TEXT).c_str());
  context->setContextProperty("bubbleName", q_name);
  QString q_folder = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_FOLDER_TEXT).c_str());
  context->setContextProperty("bubbleFolder", q_folder);
  QString q_done = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_DONE).c_str());
  context->setContextProperty("bubbleDone", q_done);
  QString q_remove = QString::fromUtf8(l10n_util::GetStringUTF8(IDS_BOOMARK_BUBBLE_REMOVE_BOOKMARK).c_str());
  context->setContextProperty("bubbleRemove", q_remove);

//  context->setContextProperty("bubbleModel", impl_);
  context->setContextProperty("bubbleFolderModel", QVariant::fromValue(folderList_));

  BookmarkModel* model = profile_->GetBookmarkModel();
  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
  const std::string& title = UTF16ToUTF8(node->GetTitle());
  QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
  QString q_node_title = QString::fromStdString(title);
  context->setContextProperty("bubbleNameInput", q_node_title);

  const BookmarkNode* parent = node->parent();
  const std::string& folder = UTF16ToUTF8(parent->GetTitle());
  QString q_node_folder = QString::fromStdString(folder);
  context->setContextProperty("bubbleFolderInput", q_node_folder);
}

BookmarkBubbleQt::~BookmarkBubbleQt() {
  delete impl_;
}

void BookmarkBubbleQt::Apply() {
  if (apply_edits_) {
    ApplyEdits();
  } else if (remove_bookmark_){
    BookmarkModel* model = profile_->GetBookmarkModel();
    const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
    if (node)
      model->Remove(node->parent(), node->parent()->GetIndexOf(node));
  }
}

void BookmarkBubbleQt::OnRemoveClicked() {
//  UserMetrics::RecordAction(UserMetricsAction("BookmarkBubble_Unstar"),
//                            profile_);

  apply_edits_ = false;
  remove_bookmark_ = true;
  Apply();
}

void BookmarkBubbleQt::ApplyEdits() {
  // Set this to make sure we don't attempt to apply edits again.
  apply_edits_ = false;

  BookmarkModel* model = profile_->GetBookmarkModel();
  const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_);
  if (node) {
    const string16 new_title = UTF8ToUTF16(name_.toUtf8().data());
    if (new_title != node->GetTitle()) {
      model->SetTitle(node, new_title);
      UserMetrics::RecordAction(
          UserMetricsAction("BookmarkBubble_ChangeTitleInBubble"),
          profile_);
    }

    // Last index means 'Create Application Bookmark...'
    if (folder_index_ < folder_combo_model_->GetItemCount() - 1) {
      const BookmarkNode* new_parent =
               folder_combo_model_->GetNodeAt(folder_index_);
      if (new_parent != node->parent()) {
        UserMetrics::RecordAction(
            UserMetricsAction("BookmarkBubble_ChangeParent"), profile_);
       if (newly_bookmarked_) {
          model->Move(node, new_parent, new_parent->child_count());
        } else {
          model->Copy(node, new_parent, new_parent->child_count());
        }
      }
    }

    if (folder_index_ == folder_combo_model_->GetItemCount() - 1) {
       //TODO ./brower/browser.cc RegisterAppPrefs, ConvertContentsToApplication
      if(newly_bookmarked_) {
        model->Remove(node->parent(), node->parent()->GetIndexOf(node));
      }
      TabContents* current_tab_contents =
                         browser_->tabstrip_model()->GetSelectedTabContents()->tab_contents();

       // Prepare data
      web_app::GetShortcutInfoForTab(current_tab_contents, &shortcut_info_);
      shortcut_info_.create_on_desktop = true;
      shortcut_info_.create_in_quick_launch_bar = false;
      shortcut_info_.create_in_applications_menu = false;

      web_app::CreateShortcut(current_tab_contents->profile()->GetPath(),
                          shortcut_info_,
                          NULL);

    //  current_tab_contents->SetAppIcon(shortcut_info_.favicon);
   //   if (current_tab_contents->delegate())
   //      current_tab_contents->delegate()->ConvertContentsToApplication(current_tab_contents);

    }
  }
}

std::string BookmarkBubbleQt::GetTitle() {
  BookmarkModel* bookmark_model= profile_->GetBookmarkModel();
  const BookmarkNode* node =
      bookmark_model->GetMostRecentlyAddedNodeForURL(url_);
  if (!node) {
    NOTREACHED();
    return std::string();
  }

  return UTF16ToUTF8(node->GetTitle());
}

void BookmarkBubbleQt::OnDoneClicked() {
  apply_edits_ = true;
  remove_bookmark_ = false;
  Apply();
}

void BookmarkBubbleQt::InitFolderComboModel() {
  folder_combo_model_.reset(new RecentlyUsedFoldersComboModel(
      profile_->GetBookmarkModel(),
      profile_->GetBookmarkModel()->GetMostRecentlyAddedNodeForURL(url_)));

  for (int index = 0; index < folder_combo_model_->GetItemCount(); index ++) {
     QString folderName =
           QString::fromStdString(UTF16ToUTF8(folder_combo_model_->GetItemAt(index)));
     folderList_.append(folderName);
  }
}

// Displays the bubble at the given coords. |point| is intentionally not const.
void BookmarkBubbleQt::PopupAt(gfx::Point point)
{
  impl_->PopupAt(point.x(), point.y());
}

#include "moc_bookmark_bubble_qt.cc"
<|endoftext|>