<commit_before>/* -------------------------------------------------------------------------- *
 *                      SimTK Core: SimTK Simbody(tm)                         *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK Core biosimulation toolkit originating from      *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 2007 Stanford University and the Authors.           *
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

#include "SimTKmath.h"
#include "simbody/internal/MobilizedBody.h"
#include "simbody/internal/MultibodySystem.h"
#include "simbody/internal/LocalEnergyMinimizer.h"
#include "simbody/internal/SimbodyMatterSubsystem.h"
#include <vector>
#include <map>

using namespace SimTK;
using namespace std;

/**
 * This class defines the objective function which is passed to the Optimizer.
 */

class LocalEnergyMinimizer::OptimizerFunction : public OptimizerSystem {
public:
    // stateIn must be realized to Model stage already.
    OptimizerFunction(const MultibodySystem& system, const State& stateIn)
    :   OptimizerSystem(stateIn.getNQ()), system(system), state(stateIn) {
        state.updU() = 0;   // no velocities
        system.realize(state, Stage::Time); // we'll only change Position stage and above
        setNumEqualityConstraints(state.getNQErr());
    }
    int objectiveFunc(const Vector& parameters, const bool new_parameters, Real& f) const {
        if (new_parameters)
            state.updQ() = parameters;
        system.realize(state, Stage::Dynamics);
        f = system.calcPotentialEnergy(state);
        return 0;
    }
    int gradientFunc(const Vector& parameters, const bool new_parameters, Vector& gradient) const  {
        if (new_parameters)
            state.updQ() = parameters;
        system.realize(state, Stage::Dynamics);
        Vector_<SpatialVec> dEdR = system.getRigidBodyForces(state, Stage::Dynamics);
        const SimbodyMatterSubsystem& matter = system.getMatterSubsystem();
        Vector dEdU;
        matter.calcInternalGradientFromSpatial(state, dEdR, dEdU);
        dEdU -= system.getMobilityForces(state, Stage::Dynamics);
        matter.multiplyByNInv(state, true, -1.0*dEdU, gradient);
        return 0;
    }
    int constraintFunc(const Vector& parameters, const bool new_parameters, Vector& constraints) const {
        state.updQ() = parameters;
        system.realize(state, Stage::Position);
        constraints = state.getQErr();
        return 0;
    }
    void optimize(Vector& q, Real tolerance) {
        Optimizer opt(*this);
        opt.useNumericalJacobian(true);
        opt.setConvergenceTolerance(tolerance);
        opt.optimize(q);
    }
private:
    const MultibodySystem& system;
    mutable State state;
};

void LocalEnergyMinimizer::minimizeEnergy(const MultibodySystem& system, State& state, Real tolerance) {
    const SimbodyMatterSubsystem& matter = system.getMatterSubsystem();
    State tempState = state;
    matter.setUseEulerAngles(tempState, true);
    system.realizeModel(tempState);
    if (!matter.getUseEulerAngles(state))
        matter.convertToEulerAngles(state, tempState);
    OptimizerFunction optimizer(system, tempState);
    Vector q = tempState.getQ();
    optimizer.optimize(q, tolerance);
    if (matter.getUseEulerAngles(state))
        state.updQ() = q;
    else {
        tempState.updQ() = q;
        matter.convertToQuaternions(tempState, state);
    }
}
<commit_msg>Make LocalEnergyMinimizer do a final realize.<commit_after>/* -------------------------------------------------------------------------- *
 *                      SimTK Core: SimTK Simbody(tm)                         *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK Core biosimulation toolkit originating from      *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 2007 Stanford University and the Authors.           *
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

#include "SimTKmath.h"
#include "simbody/internal/MobilizedBody.h"
#include "simbody/internal/MultibodySystem.h"
#include "simbody/internal/LocalEnergyMinimizer.h"
#include "simbody/internal/SimbodyMatterSubsystem.h"
#include <vector>
#include <map>

using namespace SimTK;
using namespace std;

/**
 * This class defines the objective function which is passed to the Optimizer.
 */

class LocalEnergyMinimizer::OptimizerFunction : public OptimizerSystem {
public:
    // stateIn must be realized to Model stage already.
    OptimizerFunction(const MultibodySystem& system, const State& stateIn)
    :   OptimizerSystem(stateIn.getNQ()), system(system), state(stateIn) {
        state.updU() = 0;   // no velocities
        system.realize(state, Stage::Time); // we'll only change Position stage and above
        setNumEqualityConstraints(state.getNQErr());
    }
    int objectiveFunc(const Vector& parameters, const bool new_parameters, Real& f) const {
        if (new_parameters)
            state.updQ() = parameters;
        system.realize(state, Stage::Dynamics);
        f = system.calcPotentialEnergy(state);
        return 0;
    }
    int gradientFunc(const Vector& parameters, const bool new_parameters, Vector& gradient) const  {
        if (new_parameters)
            state.updQ() = parameters;
        system.realize(state, Stage::Dynamics);
        Vector_<SpatialVec> dEdR = system.getRigidBodyForces(state, Stage::Dynamics);
        const SimbodyMatterSubsystem& matter = system.getMatterSubsystem();
        Vector dEdU;
        matter.calcInternalGradientFromSpatial(state, dEdR, dEdU);
        dEdU -= system.getMobilityForces(state, Stage::Dynamics);
        matter.multiplyByNInv(state, true, -1.0*dEdU, gradient);
        return 0;
    }
    int constraintFunc(const Vector& parameters, const bool new_parameters, Vector& constraints) const {
        state.updQ() = parameters;
        system.realize(state, Stage::Position);
        constraints = state.getQErr();
        return 0;
    }
    void optimize(Vector& q, Real tolerance) {
        Optimizer opt(*this);
        opt.useNumericalJacobian(true);
        opt.setConvergenceTolerance(tolerance);
        opt.optimize(q);
    }
private:
    const MultibodySystem& system;
    mutable State state;
};

void LocalEnergyMinimizer::minimizeEnergy(const MultibodySystem& system, State& state, Real tolerance) {
    const SimbodyMatterSubsystem& matter = system.getMatterSubsystem();
    State tempState = state;
    matter.setUseEulerAngles(tempState, true);
    system.realizeModel(tempState);
    if (!matter.getUseEulerAngles(state))
        matter.convertToEulerAngles(state, tempState);
    OptimizerFunction optimizer(system, tempState);
    Vector q = tempState.getQ();
    optimizer.optimize(q, tolerance);
    if (matter.getUseEulerAngles(state))
        state.updQ() = q;
    else {
        tempState.updQ() = q;
        matter.convertToQuaternions(tempState, state);
    }
    system.realize(state, Stage::Dynamics);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/containers.hh
 ** \brief Some syntactic sugar to look for things in STL containers.
 */

#ifndef LIBPORT_CONTAINERS_HH
# define LIBPORT_CONTAINERS_HH

# include <deque>
# include <iosfwd>
# include <list>
# include <set>
# include <vector>

namespace libport
{

  /// Invoke delete on all the members of \a c, and clear it.
  template<typename Container>
  void
  deep_clear(Container& c);

  /// Find \a v in the whole \a c.
  template<typename Container>
  inline typename Container::const_iterator
  find(const Container& c, const typename Container::value_type& v);

  /// Find \a v in the whole \a c.
  template<typename Container>
  inline typename Container::iterator
  find(Container& c, const typename Container::value_type& v);

  /// Look up for \c k in \a c, return its value, or 0 if unknown.
  ///
  /// For associative containers mapping pointers.
  template<typename Container>
  inline typename Container::mapped_type
  find0(Container& c, const typename Container::key_type& k);

  /// Apply \a f to all the members of \a c, and return it.
  template<typename Container, typename Functor>
  inline Functor&
  for_each(Container& c, Functor& v);

  /// Is \a v member of \a c?
  template<typename Container>
  inline bool
  has(const Container& c, const typename Container::value_type& v);

  /// Is \a v member of \a c?  Use member find (set, map, hash_map).
  template<typename Container>
  inline bool
  mhas(const Container& c, const typename Container::key_type& v);

  /// Insert or update \a key -> \a value in \a map, return iterator to it.
  template<typename Map>
  typename Map::iterator
  put(Map& map,
      const typename Map::key_type& key,
      const typename Map::mapped_type& value);

  // Does at least one member of \a c satisfy predicate \a f ?
  template<typename Container, typename Functor>
  bool
  has_if(const Container& c, const Functor& f);

  // Erase members of \a c satisfying predicate \a f. This does not
  // preserve the order of the members in the container.
  template<typename Container, typename Functor>
  void
  erase_if(Container& c, const Functor& f);

} // namespace libport

namespace std
{

  /*---------------------.
  | Container << Value.  |
  `---------------------*/

#define APPLY_ON_BACK_INSERTION_CONTAINERS(Macro)       \
  Macro(::std::deque);                                  \
  Macro(::std::list);                                   \
  Macro(::std::vector);

  // Push back with '<<'.
#define INSERT(Container)                               \
  template<typename Lhs, typename Alloc,                \
           typename Rhs>                                \
  Container<Lhs, Alloc>&                                \
  operator<<(Container<Lhs, Alloc>& c, const Rhs& v)

  APPLY_ON_BACK_INSERTION_CONTAINERS(INSERT)

#undef INSERT

  /*---------------------------------.
  | Associative Container << Value.  |
  `---------------------------------*/

#define APPLY_ON_ASSOCIATIVE_CONTAINERS(Macro)  \
  Macro(::std::set);

  // Insert with '<<'.
#define INSERT(Container)                               \
  template<typename Lhs, typename Alloc,                \
           typename Rhs>                                \
  Container<Lhs, Alloc>&                                \
  operator<<(Container<Lhs, Alloc>& c, const Rhs& v)

  APPLY_ON_ASSOCIATIVE_CONTAINERS(INSERT)

#undef INSERT

  /*-------------------------.
  | Container == Container.  |
  `-------------------------*/

namespace libport
{
#define APPLY_ON_CONTAINERS(Macro)              \
  APPLY_ON_ASSOCIATIVE_CONTAINERS(Macro)        \
  APPLY_ON_BACK_INSERTION_CONTAINERS(Macro)

  // ::std::list already provides this.
#define APPLY_ON_EQUAL_CONTAINERS(Macro)        \
  Macro(::std::deque);                          \
  Macro(::std::vector);                         \
  Macro(::std::set);

  // Compare two containers.
#define LIBPORT_CONTAINERS_DECLARE_EQUAL(Container)                     \
  template <typename E, typename A>                                     \
  bool operator==(const Container<E, A>& lhs,                           \
                  const Container<E, A>& rhs);

  APPLY_ON_EQUAL_CONTAINERS(LIBPORT_CONTAINERS_DECLARE_EQUAL)
#undef LIBPORT_CONTAINERS_DECLARE_EQUAL
}

  /*-------------------------.
  | Container << Container.  |
  `-------------------------*/

#define APPLY_ON_CONTAINERS_CONTAINERS(Macro)   \
  Macro(::std::deque,  ::std::deque);           \
  Macro(::std::list,   ::std::list);            \
  Macro(::std::list,   ::std::set);             \
  Macro(::std::set,    ::std::set);             \
  Macro(::std::set,    ::std::vector);          \
  Macro(::std::vector, ::std::set);             \
  Macro(::std::vector, ::std::vector);

  // Concatenate with '<<'.
  // Arguably concatenation should be `+='.  Consider the case
  // of appending a container to a container of containers.  Or use
  // an intermediate function, say 'c1 << contents(c2)'.
#define INSERT(Cont1, Cont2)                    \
  template<typename Lhs, typename Alloc1,       \
           typename Rhs, typename Alloc2>       \
  Cont1<Lhs, Alloc1>&                           \
  operator<< (Cont1<Lhs, Alloc1>& c,            \
              const Cont2<Rhs, Alloc2>& vs)

  APPLY_ON_CONTAINERS_CONTAINERS(INSERT)

#undef INSERT

} // namespace std

# include <libport/containers.hxx>

#endif // !LIBPORT_CONTAINERS_HH
<commit_msg>Add << operator to print vectors.<commit_after>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/containers.hh
 ** \brief Some syntactic sugar to look for things in STL containers.
 */

#ifndef LIBPORT_CONTAINERS_HH
# define LIBPORT_CONTAINERS_HH

# include <deque>
# include <iosfwd>
# include <list>
# include <set>
# include <vector>

# include <libport/foreach.hh>

namespace libport
{

  /// Invoke delete on all the members of \a c, and clear it.
  template<typename Container>
  void
  deep_clear(Container& c);

  /// Find \a v in the whole \a c.
  template<typename Container>
  inline typename Container::const_iterator
  find(const Container& c, const typename Container::value_type& v);

  /// Find \a v in the whole \a c.
  template<typename Container>
  inline typename Container::iterator
  find(Container& c, const typename Container::value_type& v);

  /// Look up for \c k in \a c, return its value, or 0 if unknown.
  ///
  /// For associative containers mapping pointers.
  template<typename Container>
  inline typename Container::mapped_type
  find0(Container& c, const typename Container::key_type& k);

  /// Apply \a f to all the members of \a c, and return it.
  template<typename Container, typename Functor>
  inline Functor&
  for_each(Container& c, Functor& v);

  /// Is \a v member of \a c?
  template<typename Container>
  inline bool
  has(const Container& c, const typename Container::value_type& v);

  /// Is \a v member of \a c?  Use member find (set, map, hash_map).
  template<typename Container>
  inline bool
  mhas(const Container& c, const typename Container::key_type& v);

  /// Insert or update \a key -> \a value in \a map, return iterator to it.
  template<typename Map>
  typename Map::iterator
  put(Map& map,
      const typename Map::key_type& key,
      const typename Map::mapped_type& value);

  // Does at least one member of \a c satisfy predicate \a f ?
  template<typename Container, typename Functor>
  bool
  has_if(const Container& c, const Functor& f);

  // Erase members of \a c satisfying predicate \a f. This does not
  // preserve the order of the members in the container.
  template<typename Container, typename Functor>
  void
  erase_if(Container& c, const Functor& f);

} // namespace libport

namespace std
{

  /*---------------------.
  | Container << Value.  |
  `---------------------*/

#define APPLY_ON_BACK_INSERTION_CONTAINERS(Macro)       \
  Macro(::std::deque);                                  \
  Macro(::std::list);                                   \
  Macro(::std::vector);

  // Push back with '<<'.
#define INSERT(Container)                               \
  template<typename Lhs, typename Alloc,                \
           typename Rhs>                                \
  Container<Lhs, Alloc>&                                \
  operator<<(Container<Lhs, Alloc>& c, const Rhs& v)

  APPLY_ON_BACK_INSERTION_CONTAINERS(INSERT)

#undef INSERT

  /*---------------------------------.
  | Associative Container << Value.  |
  `---------------------------------*/

#define APPLY_ON_ASSOCIATIVE_CONTAINERS(Macro)  \
  Macro(::std::set);

  // Insert with '<<'.
#define INSERT(Container)                               \
  template<typename Lhs, typename Alloc,                \
           typename Rhs>                                \
  Container<Lhs, Alloc>&                                \
  operator<<(Container<Lhs, Alloc>& c, const Rhs& v)

  APPLY_ON_ASSOCIATIVE_CONTAINERS(INSERT)

#undef INSERT

  /*-------------------------.
  | Container == Container.  |
  `-------------------------*/

namespace libport
{
#define APPLY_ON_CONTAINERS(Macro)              \
  APPLY_ON_ASSOCIATIVE_CONTAINERS(Macro)        \
  APPLY_ON_BACK_INSERTION_CONTAINERS(Macro)

  // ::std::list already provides this.
#define APPLY_ON_EQUAL_CONTAINERS(Macro)        \
  Macro(::std::deque);                          \
  Macro(::std::vector);                         \
  Macro(::std::set);

  // Compare two containers.
#define LIBPORT_CONTAINERS_DECLARE_EQUAL(Container)                     \
  template <typename E, typename A>                                     \
  bool operator==(const Container<E, A>& lhs,                           \
                  const Container<E, A>& rhs);

  APPLY_ON_EQUAL_CONTAINERS(LIBPORT_CONTAINERS_DECLARE_EQUAL)
#undef LIBPORT_CONTAINERS_DECLARE_EQUAL
}

  /*-------------------------.
  | Container << Container.  |
  `-------------------------*/

#define APPLY_ON_CONTAINERS_CONTAINERS(Macro)   \
  Macro(::std::deque,  ::std::deque);           \
  Macro(::std::list,   ::std::list);            \
  Macro(::std::list,   ::std::set);             \
  Macro(::std::set,    ::std::set);             \
  Macro(::std::set,    ::std::vector);          \
  Macro(::std::vector, ::std::set);             \
  Macro(::std::vector, ::std::vector);

  // Concatenate with '<<'.
  // Arguably concatenation should be `+='.  Consider the case
  // of appending a container to a container of containers.  Or use
  // an intermediate function, say 'c1 << contents(c2)'.
#define INSERT(Cont1, Cont2)                    \
  template<typename Lhs, typename Alloc1,       \
           typename Rhs, typename Alloc2>       \
  Cont1<Lhs, Alloc1>&                           \
  operator<< (Cont1<Lhs, Alloc1>& c,            \
              const Cont2<Rhs, Alloc2>& vs)

  APPLY_ON_CONTAINERS_CONTAINERS(INSERT)

#undef INSERT

  /*--------------------.
  | ostream << vector.  |
  `--------------------*/

  template <typename T, typename Alloc>
  std::ostream&
  operator<< (std::ostream& out, const std::vector<T, Alloc>& c)
  {
    out << "[";
    typedef typename std::vector<T, Alloc>::value_type value_type;
    foreach (const value_type& v, c)
      out << v << ", ";
    out << "]";
    return out;
  }

} // namespace std

# include <libport/containers.hxx>

#endif // !LIBPORT_CONTAINERS_HH
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_ASSERT

#include "libtorrent/config.hpp"
#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG)

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define TORRENT_ASSERT(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#endif

#endif

<commit_msg>fixed warning on gcc 4.3<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_ASSERT

#include "libtorrent/config.hpp"
#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG)

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__); } while (false)

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#endif

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_SOCKET_WIN_HPP_INCLUDED
#define TORRENT_SOCKET_WIN_HPP_INCLUDED

// TODO: remove the dependency of
// platform specific headers here.
// sockaddr_in is hard to get rid of in a nice way

#if defined(_WIN32)
	#include <winsock2.h>
#else
	#include <unistd.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <netdb.h>
	#include <errno.h>
	#include <pthread.h>
	#include <fcntl.h>
	#include <arpa/inet.h>
#endif

#include <boost/smart_ptr.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>

#include <vector>
#include <exception>
#include <string>

namespace libtorrent
{

	class network_error : public std::exception
	{
	public:
		network_error(int error_code): m_error_code(error_code) {}
		virtual const char* what() const throw();
	private:
		int m_error_code;
	};

	class socket;

	class address
	{
	friend class socket;
	public:
		address();
		address(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned short  port);
		address(unsigned int addr, unsigned short port);
		address(const std::string& addr, unsigned short port);
		address(const address& a);
		~address();

		std::string as_string() const;
		unsigned int ip() const { return m_sockaddr.sin_addr.s_addr; }
		unsigned short port() const { return htons(m_sockaddr.sin_port); }

		bool operator<(const address& a) const { if (ip() == a.ip()) return port() < a.port(); else return ip() < a.ip(); }
		bool operator!=(const address& a) const { return (ip() != a.ip()) || port() != a.port(); }
		bool operator==(const address& a) const { return (ip() == a.ip()) && port() == a.port(); }

	private:

		sockaddr_in m_sockaddr;
	};

	class socket: public boost::noncopyable
	{
	friend class address;
	friend class selector;
	public:

		enum type
		{
			tcp = 0,
			udp
		};

		socket(type t, bool blocking = true, unsigned short receive_port = 0);
		virtual ~socket();

		void connect(const address& addr);
		void close();

		void set_blocking(bool blocking);
		bool is_blocking() { return m_blocking; }

		const address& sender() const { return m_sender; }
		address name() const;

		void listen(unsigned short port, int queue);
		boost::shared_ptr<libtorrent::socket> accept();

		template<class T> int send(const T& buffer);
		template<class T> int send_to(const address& addr, const T& buffer);
		template<class T> int receive(T& buf);

		int send(const char* buffer, int size);
		int send_to(const address& addr, const char* buffer, int size);
		int receive(char* buffer, int size);

		void set_receive_bufsize(int size);
		void set_send_bufsize(int size);

		bool is_readable() const;
		bool is_writable() const;

		enum error_code
		{
			netdown,
			fault,
			access,
			address_in_use,
			address_not_available,
			in_progress,
			interrupted,
			invalid,
			net_reset,
			not_connected,
			no_buffers,
			operation_not_supported,
			not_socket,
			shutdown,
			would_block,
			connection_reset,
			timed_out,
			connection_aborted,
			message_size,
			not_ready,
			no_support,
			connection_refused,
			is_connected,
			net_unreachable,
			not_initialized,
			unknown_error
		};

		error_code last_error() const;

	private:

		socket(int sock, const address& sender);

		int m_socket;
		address m_sender;
		bool m_blocking;

#ifndef NDEBUG
		bool m_connected; // indicates that this socket has been connected
		type m_type;
#endif

	};

	template<class T>
	inline int socket::send(const T& buf)
	{
		return send(reinterpret_cast<const char*>(&buf), sizeof(buf));
	}

	template<class T>
	inline int socket::send_to(const address& addr, const T& buf)
	{
		return send_to(addr, reinterpret_cast<const unsigned char*>(&buf), sizeof(buf));
	}

	template<class T>
	inline int socket::receive(T& buf)
	{
		return receive(reinterpret_cast<char*>(&buf), sizeof(T));
	}

	// timeout is given in microseconds
	// modified is cleared and filled with the sockets that is ready for reading or writing
	// or have had an error

	class selector
	{
	public:

		void monitor_readability(boost::shared_ptr<socket> s) { m_readable.push_back(s); }
		void monitor_writability(boost::shared_ptr<socket> s) { m_writable.push_back(s); }
		void monitor_errors(boost::shared_ptr<socket> s) { m_error.push_back(s); }
/*
		void clear_readable() { m_readable.clear(); }
		void clear_writable() { m_writable.clear(); }
*/
		void remove(boost::shared_ptr<socket> s);

		void remove_writable(boost::shared_ptr<socket> s)
		{ m_writable.erase(std::find(m_writable.begin(), m_writable.end(), s)); }

		bool is_writability_monitored(boost::shared_ptr<socket> s)
		{
			return std::find(m_writable.begin(), m_writable.end(), s)
				!= m_writable.end();
		}

		void wait(int timeout
			, std::vector<boost::shared_ptr<socket> >& readable
			, std::vector<boost::shared_ptr<socket> >& writable
			, std::vector<boost::shared_ptr<socket> >& error);

		int count_read_monitors() const { return m_readable.size(); }

	private:

		std::vector<boost::shared_ptr<socket> > m_readable;
		std::vector<boost::shared_ptr<socket> > m_writable;
		std::vector<boost::shared_ptr<socket> > m_error;
	};

}

#endif // TORRENT_SOCKET_WIN_HPP_INCLUDED
<commit_msg>Made the socket.hpp platform independent<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_SOCKET_HPP_INCLUDED
#define TORRENT_SOCKET_HPP_INCLUDED

// TODO: remove the dependency of
// platform specific headers here.
// sockaddr_in is hard to get rid of in a nice way

#if defined(_WIN32)
	#include <winsock2.h>
#else
	#include <unistd.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <netdb.h>
	#include <errno.h>
	#include <pthread.h>
	#include <fcntl.h>
	#include <arpa/inet.h>
#endif

#include <boost/smart_ptr.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>

#include <vector>
#include <exception>
#include <string>

namespace libtorrent
{

	class network_error : public std::exception
	{
	public:
		network_error(int error_code): m_error_code(error_code) {}
		virtual const char* what() const throw();
	private:
		int m_error_code;
	};

	class socket;

	class address
	{
	friend class socket;
	public:
		address();
		address(
			unsigned char a
			, unsigned char b
			, unsigned char c
			, unsigned char d
			, unsigned short port);

		address(unsigned int addr, unsigned short port);

		address(const std::string& addr, unsigned short port);
		address(const address& a);
		~address();

		std::string as_string() const;
		unsigned int ip() const { return m_ip; }
		unsigned short port() const { return m_port; }

		bool operator<(const address& a) const
		{ if (ip() == a.ip()) return port() < a.port(); else return ip() < a.ip(); }
		bool operator!=(const address& a) const
		{ return (ip() != a.ip()) || port() != a.port(); }
		bool operator==(const address& a) const
		{ return (ip() == a.ip()) && port() == a.port(); }

	private:

		unsigned int m_ip;
		unsigned short m_port;
	};

	class socket: public boost::noncopyable
	{
	friend class address;
	friend class selector;
	public:

		enum type
		{
			tcp = 0,
			udp
		};

		socket(type t, bool blocking = true, unsigned short receive_port = 0);
		virtual ~socket();

		void connect(const address& addr);
		void close();

		void set_blocking(bool blocking);
		bool is_blocking() { return m_blocking; }

		const address& sender() const { return m_sender; }
		address name() const;

		void listen(unsigned short port, int queue);
		boost::shared_ptr<libtorrent::socket> accept();

		template<class T> int send(const T& buffer);
		template<class T> int send_to(const address& addr, const T& buffer);
		template<class T> int receive(T& buf);

		int send(const char* buffer, int size);
		int send_to(const address& addr, const char* buffer, int size);
		int receive(char* buffer, int size);

		void set_receive_bufsize(int size);
		void set_send_bufsize(int size);

		bool is_readable() const;
		bool is_writable() const;

		enum error_code
		{
			netdown,
			fault,
			access,
			address_in_use,
			address_not_available,
			in_progress,
			interrupted,
			invalid,
			net_reset,
			not_connected,
			no_buffers,
			operation_not_supported,
			not_socket,
			shutdown,
			would_block,
			connection_reset,
			timed_out,
			connection_aborted,
			message_size,
			not_ready,
			no_support,
			connection_refused,
			is_connected,
			net_unreachable,
			not_initialized,
			unknown_error
		};

		error_code last_error() const;

	private:

		socket(int sock, const address& sender);

		int m_socket;
		address m_sender;
		bool m_blocking;

#ifndef NDEBUG
		bool m_connected; // indicates that this socket has been connected
		type m_type;
#endif

	};

	template<class T>
	inline int socket::send(const T& buf)
	{
		return send(reinterpret_cast<const char*>(&buf), sizeof(buf));
	}

	template<class T>
	inline int socket::send_to(const address& addr, const T& buf)
	{
		return send_to(addr, reinterpret_cast<const unsigned char*>(&buf), sizeof(buf));
	}

	template<class T>
	inline int socket::receive(T& buf)
	{
		return receive(reinterpret_cast<char*>(&buf), sizeof(T));
	}

	// timeout is given in microseconds
	// modified is cleared and filled with the sockets that is ready for reading or writing
	// or have had an error

	class selector
	{
	public:

		void monitor_readability(boost::shared_ptr<socket> s) { m_readable.push_back(s); }
		void monitor_writability(boost::shared_ptr<socket> s) { m_writable.push_back(s); }
		void monitor_errors(boost::shared_ptr<socket> s) { m_error.push_back(s); }
/*
		void clear_readable() { m_readable.clear(); }
		void clear_writable() { m_writable.clear(); }
*/
		void remove(boost::shared_ptr<socket> s);

		void remove_writable(boost::shared_ptr<socket> s)
		{ m_writable.erase(std::find(m_writable.begin(), m_writable.end(), s)); }

		bool is_writability_monitored(boost::shared_ptr<socket> s)
		{
			return std::find(m_writable.begin(), m_writable.end(), s)
				!= m_writable.end();
		}

		void wait(int timeout
			, std::vector<boost::shared_ptr<socket> >& readable
			, std::vector<boost::shared_ptr<socket> >& writable
			, std::vector<boost::shared_ptr<socket> >& error);

		int count_read_monitors() const { return m_readable.size(); }

	private:

		std::vector<boost::shared_ptr<socket> > m_readable;
		std::vector<boost::shared_ptr<socket> > m_writable;
		std::vector<boost::shared_ptr<socket> > m_error;
	};

}

#endif // TORRENT_SOCKET_WIN_INCLUDED

<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_THREAD_HPP_INCLUDED
#define TORRENT_THREAD_HPP_INCLUDED

#include "libtorrent/config.hpp"

#include <memory>

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#include <memory> // for auto_ptr required by asio

#include <boost/asio/detail/thread.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/event.hpp>

#if TORRENT_USE_POSIX_SEMAPHORE
#include <semaphore.h>      // sem_*
#endif

#if TORRENT_USE_MACH_SEMAPHORE
#include <mach/semaphore.h> // semaphore_signal, semaphore_wait
#include <mach/task.h>      // semaphore_create, semaphore_destroy
#include <mach/mach_init.h> // current_task
#endif

namespace libtorrent
{
	typedef boost::asio::detail::thread thread;
	typedef boost::asio::detail::mutex mutex;
	typedef boost::asio::detail::event event;

	TORRENT_EXPORT void sleep(int milliseconds);

	struct TORRENT_EXPORT condition
	{
		condition();
		~condition();
		void wait(mutex::scoped_lock& l);
		void signal_all(mutex::scoped_lock& l);
	private:
#ifdef BOOST_HAS_PTHREADS
		pthread_cond_t m_cond;
#elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
		HANDLE m_sem;
		mutex m_mutex;
		int m_num_waiters;
#else
#error not implemented
#endif
	};

	// #error these semaphores needs to release all threads that are waiting for the semaphore when signalled
#if TORRENT_USE_POSIX_SEMAPHORE
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { sem_init(&m_sem, 0, 0); }
		~semaphore() { sem_destroy(&m_sem); }
		void signal() { sem_post(&m_sem); }
		void signal_all()
		{
			int waiters = 0;
			do
			{
				// when anyone is waiting, waiters will be
				// 0 or negative. 0 means one might be waiting
				// -1 means 2 are waiting. Keep posting as long
				// we see negative values or 0
				sem_getvalue(&m_sem, &waiters);
				sem_post(&m_sem);
			} while (waiters < 0)
		}
		void wait() { sem_wait(&m_sem); }
		void timed_wait(int ms)
		{
			timespec sp = { ms / 1000, (ms % 1000) * 1000000 };
			sem_timedwait(&m_sem, &sp);
		}
		sem_t m_sem;
	};
#elif TORRENT_USE_MACH_SEMAPHORE
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { semaphore_create(current_task(), &m_sem, SYNC_POLICY_FIFO, 0); }
		~semaphore() { semaphore_destroy(current_task(), m_sem); }
		void signal() { semaphore_signal(m_sem); }
		void signal_all() { semaphore_signal_all(m_sem); }
		void wait() { semaphore_wait(m_sem); }
		void timed_wait(int ms)
		{
			mach_timespec_t sp = { ms / 1000, (ms % 1000) * 100000};
			semaphore_timedwait(m_sem, sp);
		}
		semaphore_t m_sem;
	};
#elif defined TORRENT_WINDOWS
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { m_sem = CreateSemaphore(0, 0, 100, 0); }
		~semaphore() { CloseHandle(m_sem); }
		void signal() { ReleaseSemaphore(m_sem, 1, 0); }
		void signal_all()
		{
			LONG prev = 0;
			do { ReleaseSemaphore(m_sem, 1, &prev); } while (prev > 1);
		}
		void wait() { WaitForSingleObject(m_sem, INFINITE); }
		void timed_wait(int ms) { WaitForSingleObject(m_sem, ms); }
		HANDLE m_sem;
	};
#endif
}

#endif

<commit_msg>fixed typo<commit_after>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_THREAD_HPP_INCLUDED
#define TORRENT_THREAD_HPP_INCLUDED

#include "libtorrent/config.hpp"

#include <memory>

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#include <memory> // for auto_ptr required by asio

#include <boost/asio/detail/thread.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/event.hpp>

#if TORRENT_USE_POSIX_SEMAPHORE
#include <semaphore.h>      // sem_*
#endif

#if TORRENT_USE_MACH_SEMAPHORE
#include <mach/semaphore.h> // semaphore_signal, semaphore_wait
#include <mach/task.h>      // semaphore_create, semaphore_destroy
#include <mach/mach_init.h> // current_task
#endif

namespace libtorrent
{
	typedef boost::asio::detail::thread thread;
	typedef boost::asio::detail::mutex mutex;
	typedef boost::asio::detail::event event;

	TORRENT_EXPORT void sleep(int milliseconds);

	struct TORRENT_EXPORT condition
	{
		condition();
		~condition();
		void wait(mutex::scoped_lock& l);
		void signal_all(mutex::scoped_lock& l);
	private:
#ifdef BOOST_HAS_PTHREADS
		pthread_cond_t m_cond;
#elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
		HANDLE m_sem;
		mutex m_mutex;
		int m_num_waiters;
#else
#error not implemented
#endif
	};

	// #error these semaphores needs to release all threads that are waiting for the semaphore when signalled
#if TORRENT_USE_POSIX_SEMAPHORE
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { sem_init(&m_sem, 0, 0); }
		~semaphore() { sem_destroy(&m_sem); }
		void signal() { sem_post(&m_sem); }
		void signal_all()
		{
			int waiters = 0;
			do
			{
				// when anyone is waiting, waiters will be
				// 0 or negative. 0 means one might be waiting
				// -1 means 2 are waiting. Keep posting as long
				// we see negative values or 0
				sem_getvalue(&m_sem, &waiters);
				sem_post(&m_sem);
			} while (waiters < 0);
		}
		void wait() { sem_wait(&m_sem); }
		void timed_wait(int ms)
		{
			timespec sp = { ms / 1000, (ms % 1000) * 1000000 };
			sem_timedwait(&m_sem, &sp);
		}
		sem_t m_sem;
	};
#elif TORRENT_USE_MACH_SEMAPHORE
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { semaphore_create(current_task(), &m_sem, SYNC_POLICY_FIFO, 0); }
		~semaphore() { semaphore_destroy(current_task(), m_sem); }
		void signal() { semaphore_signal(m_sem); }
		void signal_all() { semaphore_signal_all(m_sem); }
		void wait() { semaphore_wait(m_sem); }
		void timed_wait(int ms)
		{
			mach_timespec_t sp = { ms / 1000, (ms % 1000) * 100000};
			semaphore_timedwait(m_sem, sp);
		}
		semaphore_t m_sem;
	};
#elif defined TORRENT_WINDOWS
	struct TORRENT_EXPORT semaphore
	{
		semaphore() { m_sem = CreateSemaphore(0, 0, 100, 0); }
		~semaphore() { CloseHandle(m_sem); }
		void signal() { ReleaseSemaphore(m_sem, 1, 0); }
		void signal_all()
		{
			LONG prev = 0;
			do { ReleaseSemaphore(m_sem, 1, &prev); } while (prev > 1);
		}
		void wait() { WaitForSingleObject(m_sem, INFINITE); }
		void timed_wait(int ms) { WaitForSingleObject(m_sem, ms); }
		HANDLE m_sem;
	};
#endif
}

#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/plugin_updater.h"

#include <string>
#include <vector>

#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/plugin_group.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/plugins/webplugininfo.h"

namespace plugin_updater {

// Convert to a List of Groups
static void GetPluginGroups(
    std::vector<linked_ptr<PluginGroup> >* plugin_groups) {
  // Read all plugins and convert them to plugin groups
  std::vector<WebPluginInfo> web_plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &web_plugins);

  // We first search for an existing group that matches our name,
  // and only create a new group if we can't find any.
  for (size_t i = 0; i < web_plugins.size(); ++i) {
    const WebPluginInfo& web_plugin = web_plugins[i];
    PluginGroup* group = PluginGroup::FindGroupMatchingPlugin(
        *plugin_groups, web_plugin);
    if (!group) {
      group = PluginGroup::FindHardcodedPluginGroup(web_plugin);
      plugin_groups->push_back(linked_ptr<PluginGroup>(group));
    }
    group->AddPlugin(web_plugin, i);
  }
}

static DictionaryValue* CreatePluginFileSummary(
    const WebPluginInfo& plugin) {
  DictionaryValue* data = new DictionaryValue();
  data->SetString(L"path", plugin.path.value());
  data->SetStringFromUTF16(L"name", plugin.name);
  data->SetStringFromUTF16(L"version", plugin.version);
  data->SetBoolean(L"enabled", plugin.enabled);
  return data;
}

ListValue* GetPluginGroupsData() {
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);

  // Construct DictionaryValues to return to the UI
  ListValue* plugin_groups_data = new ListValue();
  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    plugin_groups_data->Append((*it)->GetDataForUI());
  }
  return plugin_groups_data;
}

void EnablePluginGroup(bool enable, const string16& group_name) {
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);

  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    if ((*it)->GetGroupName() == group_name) {
      (*it)->Enable(enable);
    }
  }
}

void EnablePluginFile(bool enable, const FilePath::StringType& path) {
  FilePath file_path(path);
  if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path))
    NPAPI::PluginList::Singleton()->EnablePlugin(file_path);
  else
    NPAPI::PluginList::Singleton()->DisablePlugin(file_path);
}

static bool enable_internal_pdf_ = true;

void DisablePluginGroupsFromPrefs(Profile* profile) {
  bool update_internal_dir = false;
  FilePath last_internal_dir =
  profile->GetPrefs()->GetFilePath(prefs::kPluginsLastInternalDirectory);
  FilePath cur_internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
      cur_internal_dir != last_internal_dir) {
    update_internal_dir = true;
    profile->GetPrefs()->SetFilePath(
        prefs::kPluginsLastInternalDirectory, cur_internal_dir);
  }

  bool found_internal_pdf = false;
  bool force_enable_internal_pdf = false;
  FilePath pdf_path;
  PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
  FilePath::StringType pdf_path_str = pdf_path.value();
  if (enable_internal_pdf_ &&
      !profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
    // We switched to the internal pdf plugin being on by default, and so we
    // need to force it to be enabled.  We only want to do it this once though,
    // i.e. we don't want to enable it again if the user disables it afterwards.
    profile->GetPrefs()->SetBoolean(prefs::kPluginsEnabledInternalPDF, true);
    force_enable_internal_pdf = true;
  }

  if (ListValue* saved_plugins_list =
          profile->GetPrefs()->GetMutableList(prefs::kPluginsPluginsList)) {
    for (ListValue::const_iterator it = saved_plugins_list->begin();
         it != saved_plugins_list->end();
         ++it) {
      if (!(*it)->IsType(Value::TYPE_DICTIONARY)) {
        LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList;
        continue;  // Oops, don't know what to do with this item.
      }

      DictionaryValue* plugin = static_cast<DictionaryValue*>(*it);
      string16 group_name;
      bool enabled = true;
      plugin->GetBoolean(L"enabled", &enabled);

      FilePath::StringType path;
      // The plugin list constains all the plugin files in addition to the
      // plugin groups.
      if (plugin->GetString(L"path", &path)) {
        // Files have a path attribute, groups don't.
        FilePath plugin_path(path);
        if (update_internal_dir &&
            FilePath::CompareIgnoreCase(plugin_path.DirName().value(),
                last_internal_dir.value()) == 0) {
          // If the internal plugin directory has changed and if the plugin
          // looks internal, update its path in the prefs.
          plugin_path = cur_internal_dir.Append(plugin_path.BaseName());
          path = plugin_path.value();
          plugin->SetString(L"path", path);
        }

        if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
          found_internal_pdf = true;
          if (!enabled && force_enable_internal_pdf) {
            enabled = true;
            plugin->SetBoolean(L"enabled", true);
          }
        }
        if (!enabled)
          NPAPI::PluginList::Singleton()->DisablePlugin(plugin_path);
      } else if (!enabled && plugin->GetStringAsUTF16(L"name", &group_name)) {
        // Otherwise this is a list of groups.
        EnablePluginGroup(false, group_name);
      }
    }
  }

  // Build the set of policy-disabled plugins once and cache it.
  // Don't do this in the constructor, there's no profile available there.
  std::set<string16> policy_disabled_plugins;
  const ListValue* plugin_blacklist =
      profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
  if (plugin_blacklist) {
    ListValue::const_iterator end(plugin_blacklist->end());
    for (ListValue::const_iterator current(plugin_blacklist->begin());
         current != end; ++current) {
      string16 plugin_name;
      if ((*current)->GetAsUTF16(&plugin_name)) {
        policy_disabled_plugins.insert(plugin_name);
      }
    }
  }
  PluginGroup::SetPolicyDisabledPluginSet(policy_disabled_plugins);

  // Disable all of the plugins and plugin groups that are disabled by policy.
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    if (PluginGroup::IsPluginNameDisabledByPolicy(it->name))
      NPAPI::PluginList::Singleton()->DisablePlugin(it->path);
  }

  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);
  std::vector<linked_ptr<PluginGroup> >::const_iterator it;
  for (it = plugin_groups.begin(); it != plugin_groups.end(); ++it) {
    string16 current_group_name = (*it)->GetGroupName();
    if (PluginGroup::IsPluginNameDisabledByPolicy(current_group_name))
      EnablePluginGroup(false, current_group_name);
  }

  if (!enable_internal_pdf_ && !found_internal_pdf) {
    // The internal PDF plugin is disabled by default, and the user hasn't
    // overridden the default.
    NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path);
  }
}

void UpdatePreferences(Profile* profile) {
  ListValue* plugins_list = profile->GetPrefs()->GetMutableList(
      prefs::kPluginsPluginsList);
  plugins_list->Clear();

  FilePath internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
    profile->GetPrefs()->SetFilePath(prefs::kPluginsLastInternalDirectory,
                                     internal_dir);

  // Add the plugin files.
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    plugins_list->Append(CreatePluginFileSummary(*it));
  }

  // Add the groups as well.
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);
  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    // Don't save preferences for vulnerable pugins.
    if (!(*it)->IsVulnerable()) {
      plugins_list->Append((*it)->GetSummary());
    }
  }
}

}  // namespace plugin_updater
<commit_msg>Disabled internal PDF by default. BUG=None TEST=Verify that the internal PDF plugin is disabled by default.s<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/plugin_updater.h"

#include <string>
#include <vector>

#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/plugin_group.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/plugins/webplugininfo.h"

namespace plugin_updater {

// Convert to a List of Groups
static void GetPluginGroups(
    std::vector<linked_ptr<PluginGroup> >* plugin_groups) {
  // Read all plugins and convert them to plugin groups
  std::vector<WebPluginInfo> web_plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &web_plugins);

  // We first search for an existing group that matches our name,
  // and only create a new group if we can't find any.
  for (size_t i = 0; i < web_plugins.size(); ++i) {
    const WebPluginInfo& web_plugin = web_plugins[i];
    PluginGroup* group = PluginGroup::FindGroupMatchingPlugin(
        *plugin_groups, web_plugin);
    if (!group) {
      group = PluginGroup::FindHardcodedPluginGroup(web_plugin);
      plugin_groups->push_back(linked_ptr<PluginGroup>(group));
    }
    group->AddPlugin(web_plugin, i);
  }
}

static DictionaryValue* CreatePluginFileSummary(
    const WebPluginInfo& plugin) {
  DictionaryValue* data = new DictionaryValue();
  data->SetString(L"path", plugin.path.value());
  data->SetStringFromUTF16(L"name", plugin.name);
  data->SetStringFromUTF16(L"version", plugin.version);
  data->SetBoolean(L"enabled", plugin.enabled);
  return data;
}

ListValue* GetPluginGroupsData() {
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);

  // Construct DictionaryValues to return to the UI
  ListValue* plugin_groups_data = new ListValue();
  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    plugin_groups_data->Append((*it)->GetDataForUI());
  }
  return plugin_groups_data;
}

void EnablePluginGroup(bool enable, const string16& group_name) {
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);

  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    if ((*it)->GetGroupName() == group_name) {
      (*it)->Enable(enable);
    }
  }
}

void EnablePluginFile(bool enable, const FilePath::StringType& path) {
  FilePath file_path(path);
  if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path))
    NPAPI::PluginList::Singleton()->EnablePlugin(file_path);
  else
    NPAPI::PluginList::Singleton()->DisablePlugin(file_path);
}

static bool enable_internal_pdf_ = false;

void DisablePluginGroupsFromPrefs(Profile* profile) {
  bool update_internal_dir = false;
  FilePath last_internal_dir =
  profile->GetPrefs()->GetFilePath(prefs::kPluginsLastInternalDirectory);
  FilePath cur_internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
      cur_internal_dir != last_internal_dir) {
    update_internal_dir = true;
    profile->GetPrefs()->SetFilePath(
        prefs::kPluginsLastInternalDirectory, cur_internal_dir);
  }

  bool found_internal_pdf = false;
  bool force_enable_internal_pdf = false;
  FilePath pdf_path;
  PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
  FilePath::StringType pdf_path_str = pdf_path.value();
  if (enable_internal_pdf_ &&
      !profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
    // We switched to the internal pdf plugin being on by default, and so we
    // need to force it to be enabled.  We only want to do it this once though,
    // i.e. we don't want to enable it again if the user disables it afterwards.
    profile->GetPrefs()->SetBoolean(prefs::kPluginsEnabledInternalPDF, true);
    force_enable_internal_pdf = true;
  }

  if (ListValue* saved_plugins_list =
          profile->GetPrefs()->GetMutableList(prefs::kPluginsPluginsList)) {
    for (ListValue::const_iterator it = saved_plugins_list->begin();
         it != saved_plugins_list->end();
         ++it) {
      if (!(*it)->IsType(Value::TYPE_DICTIONARY)) {
        LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList;
        continue;  // Oops, don't know what to do with this item.
      }

      DictionaryValue* plugin = static_cast<DictionaryValue*>(*it);
      string16 group_name;
      bool enabled = true;
      plugin->GetBoolean(L"enabled", &enabled);

      FilePath::StringType path;
      // The plugin list constains all the plugin files in addition to the
      // plugin groups.
      if (plugin->GetString(L"path", &path)) {
        // Files have a path attribute, groups don't.
        FilePath plugin_path(path);
        if (update_internal_dir &&
            FilePath::CompareIgnoreCase(plugin_path.DirName().value(),
                last_internal_dir.value()) == 0) {
          // If the internal plugin directory has changed and if the plugin
          // looks internal, update its path in the prefs.
          plugin_path = cur_internal_dir.Append(plugin_path.BaseName());
          path = plugin_path.value();
          plugin->SetString(L"path", path);
        }

        if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
          found_internal_pdf = true;
          if (!enabled && force_enable_internal_pdf) {
            enabled = true;
            plugin->SetBoolean(L"enabled", true);
          }
        }
        if (!enabled)
          NPAPI::PluginList::Singleton()->DisablePlugin(plugin_path);
      } else if (!enabled && plugin->GetStringAsUTF16(L"name", &group_name)) {
        // Otherwise this is a list of groups.
        EnablePluginGroup(false, group_name);
      }
    }
  }

  // Build the set of policy-disabled plugins once and cache it.
  // Don't do this in the constructor, there's no profile available there.
  std::set<string16> policy_disabled_plugins;
  const ListValue* plugin_blacklist =
      profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
  if (plugin_blacklist) {
    ListValue::const_iterator end(plugin_blacklist->end());
    for (ListValue::const_iterator current(plugin_blacklist->begin());
         current != end; ++current) {
      string16 plugin_name;
      if ((*current)->GetAsUTF16(&plugin_name)) {
        policy_disabled_plugins.insert(plugin_name);
      }
    }
  }
  PluginGroup::SetPolicyDisabledPluginSet(policy_disabled_plugins);

  // Disable all of the plugins and plugin groups that are disabled by policy.
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    if (PluginGroup::IsPluginNameDisabledByPolicy(it->name))
      NPAPI::PluginList::Singleton()->DisablePlugin(it->path);
  }

  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);
  std::vector<linked_ptr<PluginGroup> >::const_iterator it;
  for (it = plugin_groups.begin(); it != plugin_groups.end(); ++it) {
    string16 current_group_name = (*it)->GetGroupName();
    if (PluginGroup::IsPluginNameDisabledByPolicy(current_group_name))
      EnablePluginGroup(false, current_group_name);
  }

  if (!enable_internal_pdf_ && !found_internal_pdf) {
    // The internal PDF plugin is disabled by default, and the user hasn't
    // overridden the default.
    NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path);
  }
}

void UpdatePreferences(Profile* profile) {
  ListValue* plugins_list = profile->GetPrefs()->GetMutableList(
      prefs::kPluginsPluginsList);
  plugins_list->Clear();

  FilePath internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
    profile->GetPrefs()->SetFilePath(prefs::kPluginsLastInternalDirectory,
                                     internal_dir);

  // Add the plugin files.
  std::vector<WebPluginInfo> plugins;
  NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
  for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
       it != plugins.end();
       ++it) {
    plugins_list->Append(CreatePluginFileSummary(*it));
  }

  // Add the groups as well.
  std::vector<linked_ptr<PluginGroup> > plugin_groups;
  GetPluginGroups(&plugin_groups);
  for (std::vector<linked_ptr<PluginGroup> >::iterator it =
       plugin_groups.begin();
       it != plugin_groups.end();
       ++it) {
    // Don't save preferences for vulnerable pugins.
    if (!(*it)->IsVulnerable()) {
      plugins_list->Append((*it)->GetSummary());
    }
  }
}

}  // namespace plugin_updater
<|endoftext|>


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

#include "chrome/browser/ssl/ssl_policy.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/string_util.h"
#include "chrome/browser/cert_store.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/ssl/ssl_cert_error_handler.h"
#include "chrome/browser/ssl/ssl_error_info.h"
#include "chrome/browser/ssl/ssl_mixed_content_handler.h"
#include "chrome/browser/ssl/ssl_request_info.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "net/base/cert_status_flags.h"
#include "net/base/ssl_info.h"
#include "webkit/glue/resource_type.h"

using WebKit::WebConsoleMessage;

class SSLPolicy::ShowMixedContentTask : public Task {
 public:
  ShowMixedContentTask(SSLPolicy* policy, SSLMixedContentHandler* handler);
  virtual ~ShowMixedContentTask();

  virtual void Run();

 private:
  SSLPolicy* policy_;
  scoped_refptr<SSLMixedContentHandler> handler_;

  DISALLOW_COPY_AND_ASSIGN(ShowMixedContentTask);
};

SSLPolicy::ShowMixedContentTask::ShowMixedContentTask(SSLPolicy* policy,
                                           SSLMixedContentHandler* handler)
    : policy_(policy),
      handler_(handler) {
}

SSLPolicy::ShowMixedContentTask::~ShowMixedContentTask() {
}

void SSLPolicy::ShowMixedContentTask::Run() {
  policy_->AllowMixedContentForOrigin(handler_->frame_origin());
  policy_->AllowMixedContentForOrigin(handler_->main_frame_origin());
  policy_->backend()->Reload();
}

SSLPolicy::SSLPolicy(SSLPolicyBackend* backend)
    : backend_(backend) {
  DCHECK(backend_);
}

void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
  // First we check if we know the policy for this error.
  net::X509Certificate::Policy::Judgment judgment =
      backend_->QueryPolicy(handler->ssl_info().cert,
                            handler->request_url().host());

  if (judgment == net::X509Certificate::Policy::ALLOWED) {
    handler->ContinueRequest();
    return;
  }

  // The judgment is either DENIED or UNKNOWN.
  // For now we handle the DENIED as the UNKNOWN, which means a blocking
  // page is shown to the user every time he comes back to the page.

  switch(handler->cert_error()) {
    case net::ERR_CERT_COMMON_NAME_INVALID:
    case net::ERR_CERT_DATE_INVALID:
    case net::ERR_CERT_AUTHORITY_INVALID:
      OnOverridableCertError(handler);
      break;
    case net::ERR_CERT_NO_REVOCATION_MECHANISM:
      // Ignore this error.
      handler->ContinueRequest();
      break;
    case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
      // We ignore this error and display an infobar.
      handler->ContinueRequest();
      backend_->ShowMessage(l10n_util::GetString(
          IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR));
      break;
    case net::ERR_CERT_CONTAINS_ERRORS:
    case net::ERR_CERT_REVOKED:
    case net::ERR_CERT_INVALID:
      OnFatalCertError(handler);
      break;
    default:
      NOTREACHED();
      handler->CancelRequest();
      break;
  }
}

void SSLPolicy::OnMixedContent(SSLMixedContentHandler* handler) {
  // Get the user's mixed content preference.
  PrefService* prefs = handler->GetTabContents()->profile()->GetPrefs();
  FilterPolicy::Type filter_policy =
      FilterPolicy::FromInt(prefs->GetInteger(prefs::kMixedContentFiltering));

  // If the user has added an exception, doctor the |filter_policy|.
  std::string host = GURL(handler->main_frame_origin()).host();
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS) &&
      backend_->IsForceTLSEnabledForHost(host)) {
    // We're supposed to block all mixed content for this host.
    filter_policy = FilterPolicy::FILTER_ALL;
  } else if (backend_->DidAllowMixedContentForHost(host) ||
             backend_->DidMarkHostAsBroken(host, handler->pid())) {
    // Let the mixed content through.
    filter_policy = FilterPolicy::DONT_FILTER;
  } else if (filter_policy != FilterPolicy::DONT_FILTER) {
    backend_->ShowMessageWithLink(
        l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT),
        l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT),
        new ShowMixedContentTask(this, handler));
  }

  handler->StartRequest(filter_policy);
  AddMixedContentWarningToConsole(handler);
}

void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) {
  if (net::IsCertStatusError(info->ssl_cert_status()))
    UpdateStateForUnsafeContent(info);

  if (IsMixedContent(info->url(),
                     info->resource_type(),
                     info->filter_policy(),
                     info->frame_origin()))
    UpdateStateForMixedContent(info);
}

void SSLPolicy::UpdateEntry(NavigationEntry* entry) {
  DCHECK(entry);

  InitializeEntryIfNeeded(entry);

  if (!entry->url().SchemeIsSecure())
    return;

  // An HTTPS response may not have a certificate for some reason.  When that
  // happens, use the unauthenticated (HTTP) rather than the authentication
  // broken security style so that we can detect this error condition.
  if (!entry->ssl().cert_id()) {
    entry->ssl().set_security_style(SECURITY_STYLE_UNAUTHENTICATED);
    return;
  }

  if (net::IsCertStatusError(entry->ssl().cert_status())) {
    entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
    return;
  }

  if (backend_->DidMarkHostAsBroken(entry->url().host(),
                                   entry->site_instance()->GetProcess()->pid()))
    entry->ssl().set_has_mixed_content();
}

// static
bool SSLPolicy::IsMixedContent(const GURL& url,
                               ResourceType::Type resource_type,
                               FilterPolicy::Type filter_policy,
                               const std::string& frame_origin) {
  ////////////////////////////////////////////////////////////////////////////
  // WARNING: This function is called from both the IO and UI threads.  Do  //
  //          not touch any non-thread-safe objects!  You have been warned. //
  ////////////////////////////////////////////////////////////////////////////

  // We can't possibly have mixed content when loading the main frame.
  if (resource_type == ResourceType::MAIN_FRAME)
    return false;

  // If we've filtered the resource, then it's no longer dangerous.
  if (filter_policy != FilterPolicy::DONT_FILTER)
    return false;

  // If the frame doing the loading is already insecure, then we must have
  // already dealt with whatever mixed content might be going on.
  if (!GURL(frame_origin).SchemeIsSecure())
    return false;

  // We aren't worried about mixed content if we're loading an HTTPS URL.
  if (url.SchemeIsSecure())
    return false;

  return true;
}

////////////////////////////////////////////////////////////////////////////////
// SSLBlockingPage::Delegate methods

SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLCertErrorHandler* handler) {
  return SSLErrorInfo::CreateError(
      SSLErrorInfo::NetErrorToErrorType(handler->cert_error()),
      handler->ssl_info().cert, handler->request_url());
}

void SSLPolicy::OnDenyCertificate(SSLCertErrorHandler* handler) {
  // Default behavior for rejecting a certificate.
  //
  // While DenyCertForHost() executes synchronously on this thread,
  // CancelRequest() gets posted to a different thread. Calling
  // DenyCertForHost() first ensures deterministic ordering.
  backend_->DenyCertForHost(handler->ssl_info().cert,
                            handler->request_url().host());
  handler->CancelRequest();
}

void SSLPolicy::OnAllowCertificate(SSLCertErrorHandler* handler) {
  // Default behavior for accepting a certificate.
  // Note that we should not call SetMaxSecurityStyle here, because the active
  // NavigationEntry has just been deleted (in HideInterstitialPage) and the
  // new NavigationEntry will not be set until DidNavigate.  This is ok,
  // because the new NavigationEntry will have its max security style set
  // within DidNavigate.
  //
  // While AllowCertForHost() executes synchronously on this thread,
  // ContinueRequest() gets posted to a different thread. Calling
  // AllowCertForHost() first ensures deterministic ordering.
  backend_->AllowCertForHost(handler->ssl_info().cert,
                             handler->request_url().host());
  handler->ContinueRequest();
}

////////////////////////////////////////////////////////////////////////////////
// Certificate Error Routines

void SSLPolicy::OnOverridableCertError(SSLCertErrorHandler* handler) {
  if (handler->resource_type() != ResourceType::MAIN_FRAME) {
    // A sub-resource has a certificate error.  The user doesn't really
    // have a context for making the right decision, so block the
    // request hard, without an info bar to allow showing the insecure
    // content.
    handler->DenyRequest();
    return;
  }
  // We need to ask the user to approve this certificate.
  SSLBlockingPage* blocking_page = new SSLBlockingPage(handler, this);
  blocking_page->Show();
}

void SSLPolicy::OnFatalCertError(SSLCertErrorHandler* handler) {
  if (handler->resource_type() != ResourceType::MAIN_FRAME) {
    handler->DenyRequest();
    return;
  }
  handler->CancelRequest();
  ShowErrorPage(handler);
  // No need to degrade our security indicators because we didn't continue.
}

void SSLPolicy::ShowErrorPage(SSLCertErrorHandler* handler) {
  SSLErrorInfo error_info = GetSSLErrorInfo(handler);

  // Let's build the html error page.
  DictionaryValue strings;
  strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE));
  strings.SetString(L"headLine", error_info.title());
  strings.SetString(L"description", error_info.details());
  strings.SetString(L"moreInfoTitle",
                    l10n_util::GetString(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
  SSLBlockingPage::SetExtraInfo(&strings, error_info.extra_information());

  strings.SetString(L"back", l10n_util::GetString(IDS_SSL_ERROR_PAGE_BACK));

  strings.SetString(L"textdirection",
      (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
      L"rtl" : L"ltr");

  static const StringPiece html(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
          IDR_SSL_ERROR_HTML));

  std::string html_text(jstemplate_builder::GetTemplateHtml(html, &strings,
                                                            "template_root"));

  TabContents* tab  = handler->GetTabContents();
  int cert_id = CertStore::GetSharedInstance()->StoreCert(
      handler->ssl_info().cert, tab->render_view_host()->process()->pid());
  std::string security_info =
      SSLManager::SerializeSecurityInfo(cert_id,
                                        handler->ssl_info().cert_status,
                                        handler->ssl_info().security_bits);
  tab->render_view_host()->LoadAlternateHTMLString(html_text,
                                                   true,
                                                   handler->request_url(),
                                                   security_info);
  tab->controller().GetActiveEntry()->set_page_type(
      NavigationEntry::ERROR_PAGE);
}

void SSLPolicy::AddMixedContentWarningToConsole(
    SSLMixedContentHandler* handler) {
  const std::wstring& text = l10n_util::GetStringF(
      IDS_MIXED_CONTENT_LOG_MESSAGE,
      UTF8ToWide(handler->frame_origin()),
      UTF8ToWide(handler->request_url().spec()));
  backend_->AddMessageToConsole(
      WideToUTF16Hack(text), WebConsoleMessage::LevelWarning);
}

void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) {
  if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN)
    return;

  entry->ssl().set_security_style(entry->url().SchemeIsSecure() ?
      SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED);
}

void SSLPolicy::MarkOriginAsBroken(const std::string& origin, int pid) {
  GURL parsed_origin(origin);
  if (!parsed_origin.SchemeIsSecure())
    return;

  backend_->MarkHostAsBroken(parsed_origin.host(), pid);
}

void SSLPolicy::AllowMixedContentForOrigin(const std::string& origin) {
  GURL parsed_origin(origin);
  if (!parsed_origin.SchemeIsSecure())
    return;

  backend_->AllowMixedContentForHost(parsed_origin.host());
}

void SSLPolicy::UpdateStateForMixedContent(SSLRequestInfo* info) {
  if (info->resource_type() != ResourceType::MAIN_FRAME ||
      info->resource_type() != ResourceType::SUB_FRAME) {
    // The frame's origin now contains mixed content and therefore is broken.
    MarkOriginAsBroken(info->frame_origin(), info->pid());
  }

  if (info->resource_type() != ResourceType::MAIN_FRAME) {
    // The main frame now contains a frame with mixed content.  Therefore, we
    // mark the main frame's origin as broken too.
    MarkOriginAsBroken(info->main_frame_origin(), info->pid());
  }
}

void SSLPolicy::UpdateStateForUnsafeContent(SSLRequestInfo* info) {
  // This request as a broken cert, which means its host is broken.
  backend_->MarkHostAsBroken(info->url().host(), info->pid());
  UpdateStateForMixedContent(info);
}
<commit_msg>Fix crash when updating a navigation entry without a site_instance.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ssl/ssl_policy.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/string_util.h"
#include "chrome/browser/cert_store.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/ssl/ssl_cert_error_handler.h"
#include "chrome/browser/ssl/ssl_error_info.h"
#include "chrome/browser/ssl/ssl_mixed_content_handler.h"
#include "chrome/browser/ssl/ssl_request_info.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "net/base/cert_status_flags.h"
#include "net/base/ssl_info.h"
#include "webkit/glue/resource_type.h"

using WebKit::WebConsoleMessage;

class SSLPolicy::ShowMixedContentTask : public Task {
 public:
  ShowMixedContentTask(SSLPolicy* policy, SSLMixedContentHandler* handler);
  virtual ~ShowMixedContentTask();

  virtual void Run();

 private:
  SSLPolicy* policy_;
  scoped_refptr<SSLMixedContentHandler> handler_;

  DISALLOW_COPY_AND_ASSIGN(ShowMixedContentTask);
};

SSLPolicy::ShowMixedContentTask::ShowMixedContentTask(SSLPolicy* policy,
                                           SSLMixedContentHandler* handler)
    : policy_(policy),
      handler_(handler) {
}

SSLPolicy::ShowMixedContentTask::~ShowMixedContentTask() {
}

void SSLPolicy::ShowMixedContentTask::Run() {
  policy_->AllowMixedContentForOrigin(handler_->frame_origin());
  policy_->AllowMixedContentForOrigin(handler_->main_frame_origin());
  policy_->backend()->Reload();
}

SSLPolicy::SSLPolicy(SSLPolicyBackend* backend)
    : backend_(backend) {
  DCHECK(backend_);
}

void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
  // First we check if we know the policy for this error.
  net::X509Certificate::Policy::Judgment judgment =
      backend_->QueryPolicy(handler->ssl_info().cert,
                            handler->request_url().host());

  if (judgment == net::X509Certificate::Policy::ALLOWED) {
    handler->ContinueRequest();
    return;
  }

  // The judgment is either DENIED or UNKNOWN.
  // For now we handle the DENIED as the UNKNOWN, which means a blocking
  // page is shown to the user every time he comes back to the page.

  switch(handler->cert_error()) {
    case net::ERR_CERT_COMMON_NAME_INVALID:
    case net::ERR_CERT_DATE_INVALID:
    case net::ERR_CERT_AUTHORITY_INVALID:
      OnOverridableCertError(handler);
      break;
    case net::ERR_CERT_NO_REVOCATION_MECHANISM:
      // Ignore this error.
      handler->ContinueRequest();
      break;
    case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
      // We ignore this error and display an infobar.
      handler->ContinueRequest();
      backend_->ShowMessage(l10n_util::GetString(
          IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR));
      break;
    case net::ERR_CERT_CONTAINS_ERRORS:
    case net::ERR_CERT_REVOKED:
    case net::ERR_CERT_INVALID:
      OnFatalCertError(handler);
      break;
    default:
      NOTREACHED();
      handler->CancelRequest();
      break;
  }
}

void SSLPolicy::OnMixedContent(SSLMixedContentHandler* handler) {
  // Get the user's mixed content preference.
  PrefService* prefs = handler->GetTabContents()->profile()->GetPrefs();
  FilterPolicy::Type filter_policy =
      FilterPolicy::FromInt(prefs->GetInteger(prefs::kMixedContentFiltering));

  // If the user has added an exception, doctor the |filter_policy|.
  std::string host = GURL(handler->main_frame_origin()).host();
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS) &&
      backend_->IsForceTLSEnabledForHost(host)) {
    // We're supposed to block all mixed content for this host.
    filter_policy = FilterPolicy::FILTER_ALL;
  } else if (backend_->DidAllowMixedContentForHost(host) ||
             backend_->DidMarkHostAsBroken(host, handler->pid())) {
    // Let the mixed content through.
    filter_policy = FilterPolicy::DONT_FILTER;
  } else if (filter_policy != FilterPolicy::DONT_FILTER) {
    backend_->ShowMessageWithLink(
        l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT),
        l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT),
        new ShowMixedContentTask(this, handler));
  }

  handler->StartRequest(filter_policy);
  AddMixedContentWarningToConsole(handler);
}

void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) {
  if (net::IsCertStatusError(info->ssl_cert_status()))
    UpdateStateForUnsafeContent(info);

  if (IsMixedContent(info->url(),
                     info->resource_type(),
                     info->filter_policy(),
                     info->frame_origin()))
    UpdateStateForMixedContent(info);
}

void SSLPolicy::UpdateEntry(NavigationEntry* entry) {
  DCHECK(entry);

  InitializeEntryIfNeeded(entry);

  if (!entry->url().SchemeIsSecure())
    return;

  // An HTTPS response may not have a certificate for some reason.  When that
  // happens, use the unauthenticated (HTTP) rather than the authentication
  // broken security style so that we can detect this error condition.
  if (!entry->ssl().cert_id()) {
    entry->ssl().set_security_style(SECURITY_STYLE_UNAUTHENTICATED);
    return;
  }

  if (net::IsCertStatusError(entry->ssl().cert_status())) {
    entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
    return;
  }

  SiteInstance* site_instance = entry->site_instance();
  // Note that |site_instance| can be NULL here because NavigationEntries don't
  // necessarily have site instances.  Without a process, the entry can't
  // possibly have mixed content.  See bug http://crbug.com/12423.
  if (site_instance &&
      backend_->DidMarkHostAsBroken(entry->url().host(),
                                    site_instance->GetProcess()->pid()))
    entry->ssl().set_has_mixed_content();
}

// static
bool SSLPolicy::IsMixedContent(const GURL& url,
                               ResourceType::Type resource_type,
                               FilterPolicy::Type filter_policy,
                               const std::string& frame_origin) {
  ////////////////////////////////////////////////////////////////////////////
  // WARNING: This function is called from both the IO and UI threads.  Do  //
  //          not touch any non-thread-safe objects!  You have been warned. //
  ////////////////////////////////////////////////////////////////////////////

  // We can't possibly have mixed content when loading the main frame.
  if (resource_type == ResourceType::MAIN_FRAME)
    return false;

  // If we've filtered the resource, then it's no longer dangerous.
  if (filter_policy != FilterPolicy::DONT_FILTER)
    return false;

  // If the frame doing the loading is already insecure, then we must have
  // already dealt with whatever mixed content might be going on.
  if (!GURL(frame_origin).SchemeIsSecure())
    return false;

  // We aren't worried about mixed content if we're loading an HTTPS URL.
  if (url.SchemeIsSecure())
    return false;

  return true;
}

////////////////////////////////////////////////////////////////////////////////
// SSLBlockingPage::Delegate methods

SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLCertErrorHandler* handler) {
  return SSLErrorInfo::CreateError(
      SSLErrorInfo::NetErrorToErrorType(handler->cert_error()),
      handler->ssl_info().cert, handler->request_url());
}

void SSLPolicy::OnDenyCertificate(SSLCertErrorHandler* handler) {
  // Default behavior for rejecting a certificate.
  //
  // While DenyCertForHost() executes synchronously on this thread,
  // CancelRequest() gets posted to a different thread. Calling
  // DenyCertForHost() first ensures deterministic ordering.
  backend_->DenyCertForHost(handler->ssl_info().cert,
                            handler->request_url().host());
  handler->CancelRequest();
}

void SSLPolicy::OnAllowCertificate(SSLCertErrorHandler* handler) {
  // Default behavior for accepting a certificate.
  // Note that we should not call SetMaxSecurityStyle here, because the active
  // NavigationEntry has just been deleted (in HideInterstitialPage) and the
  // new NavigationEntry will not be set until DidNavigate.  This is ok,
  // because the new NavigationEntry will have its max security style set
  // within DidNavigate.
  //
  // While AllowCertForHost() executes synchronously on this thread,
  // ContinueRequest() gets posted to a different thread. Calling
  // AllowCertForHost() first ensures deterministic ordering.
  backend_->AllowCertForHost(handler->ssl_info().cert,
                             handler->request_url().host());
  handler->ContinueRequest();
}

////////////////////////////////////////////////////////////////////////////////
// Certificate Error Routines

void SSLPolicy::OnOverridableCertError(SSLCertErrorHandler* handler) {
  if (handler->resource_type() != ResourceType::MAIN_FRAME) {
    // A sub-resource has a certificate error.  The user doesn't really
    // have a context for making the right decision, so block the
    // request hard, without an info bar to allow showing the insecure
    // content.
    handler->DenyRequest();
    return;
  }
  // We need to ask the user to approve this certificate.
  SSLBlockingPage* blocking_page = new SSLBlockingPage(handler, this);
  blocking_page->Show();
}

void SSLPolicy::OnFatalCertError(SSLCertErrorHandler* handler) {
  if (handler->resource_type() != ResourceType::MAIN_FRAME) {
    handler->DenyRequest();
    return;
  }
  handler->CancelRequest();
  ShowErrorPage(handler);
  // No need to degrade our security indicators because we didn't continue.
}

void SSLPolicy::ShowErrorPage(SSLCertErrorHandler* handler) {
  SSLErrorInfo error_info = GetSSLErrorInfo(handler);

  // Let's build the html error page.
  DictionaryValue strings;
  strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE));
  strings.SetString(L"headLine", error_info.title());
  strings.SetString(L"description", error_info.details());
  strings.SetString(L"moreInfoTitle",
                    l10n_util::GetString(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
  SSLBlockingPage::SetExtraInfo(&strings, error_info.extra_information());

  strings.SetString(L"back", l10n_util::GetString(IDS_SSL_ERROR_PAGE_BACK));

  strings.SetString(L"textdirection",
      (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
      L"rtl" : L"ltr");

  static const StringPiece html(
      ResourceBundle::GetSharedInstance().GetRawDataResource(
          IDR_SSL_ERROR_HTML));

  std::string html_text(jstemplate_builder::GetTemplateHtml(html, &strings,
                                                            "template_root"));

  TabContents* tab  = handler->GetTabContents();
  int cert_id = CertStore::GetSharedInstance()->StoreCert(
      handler->ssl_info().cert, tab->render_view_host()->process()->pid());
  std::string security_info =
      SSLManager::SerializeSecurityInfo(cert_id,
                                        handler->ssl_info().cert_status,
                                        handler->ssl_info().security_bits);
  tab->render_view_host()->LoadAlternateHTMLString(html_text,
                                                   true,
                                                   handler->request_url(),
                                                   security_info);
  tab->controller().GetActiveEntry()->set_page_type(
      NavigationEntry::ERROR_PAGE);
}

void SSLPolicy::AddMixedContentWarningToConsole(
    SSLMixedContentHandler* handler) {
  const std::wstring& text = l10n_util::GetStringF(
      IDS_MIXED_CONTENT_LOG_MESSAGE,
      UTF8ToWide(handler->frame_origin()),
      UTF8ToWide(handler->request_url().spec()));
  backend_->AddMessageToConsole(
      WideToUTF16Hack(text), WebConsoleMessage::LevelWarning);
}

void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) {
  if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN)
    return;

  entry->ssl().set_security_style(entry->url().SchemeIsSecure() ?
      SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED);
}

void SSLPolicy::MarkOriginAsBroken(const std::string& origin, int pid) {
  GURL parsed_origin(origin);
  if (!parsed_origin.SchemeIsSecure())
    return;

  backend_->MarkHostAsBroken(parsed_origin.host(), pid);
}

void SSLPolicy::AllowMixedContentForOrigin(const std::string& origin) {
  GURL parsed_origin(origin);
  if (!parsed_origin.SchemeIsSecure())
    return;

  backend_->AllowMixedContentForHost(parsed_origin.host());
}

void SSLPolicy::UpdateStateForMixedContent(SSLRequestInfo* info) {
  if (info->resource_type() != ResourceType::MAIN_FRAME ||
      info->resource_type() != ResourceType::SUB_FRAME) {
    // The frame's origin now contains mixed content and therefore is broken.
    MarkOriginAsBroken(info->frame_origin(), info->pid());
  }

  if (info->resource_type() != ResourceType::MAIN_FRAME) {
    // The main frame now contains a frame with mixed content.  Therefore, we
    // mark the main frame's origin as broken too.
    MarkOriginAsBroken(info->main_frame_origin(), info->pid());
  }
}

void SSLPolicy::UpdateStateForUnsafeContent(SSLRequestInfo* info) {
  // This request as a broken cert, which means its host is broken.
  backend_->MarkHostAsBroken(info->url().host(), info->pid());
  UpdateStateForMixedContent(info);
}
<|endoftext|>