<commit_before>/* $Id$ */
/* Author: Toby Young, Polish Academy of Sciences,                */
/*         Wolfgang Bangerth, Texas A&M University                */
/*    $Id$        */
/*                                                                */
/*    Copyright (C) 2009 by the deal.II authors */
/*                                                                */
/*    This file is subject to QPL and may not be  distributed     */
/*    without copyright and license information. Please refer     */
/*    to the file deal.II/doc/license.html for the  text  and     */
/*    further information on this license.                        */

                                 // @sect3{Include files}

#include <base/logstream.h>
#include <base/quadrature_lib.h>
#include <base/function.h>
#include <base/function_parser.h>
#include <base/parameter_handler.h>
#include <lac/full_matrix.h>
#include <lac/petsc_sparse_matrix.h>
#include <lac/petsc_vector.h>
#include <lac/solver_cg.h>
#include <lac/precondition.h>
#include <lac/compressed_simple_sparsity_pattern.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
#include <fe/fe_q.h>
#include <fe/fe_values.h>
#include <numerics/vectors.h>
#include <numerics/matrices.h>
#include <numerics/data_out.h>

#include <fstream>
#include <iostream>

				 // The final step, as in previous
				 // programs, is to import all the
				 // deal.II class and function names
				 // into the global namespace:
using namespace dealii;

                                 // @sect3{The EigenvalueProblem class template}

template <int dim>
class EigenvalueProblem
{
  public:
    EigenvalueProblem ();
    void run ();

  private:
    void make_grid_and_dofs ();
    void assemble_system ();
    void solve ();
    void output_results () const;

    Triangulation<dim>   triangulation;
    FE_Q<dim>            fe;
    DoFHandler<dim>      dof_handler;

    PETScWrappers::SparseMatrix        stiffness_matrix, mass_matrix;
    std::vector<PETScWrappers::Vector> eigenfunctions;

    ParameterHandler parameters;
};

                                 // @sect3{Implementation of the EigenvalueProblem class}

                                 // @sect4{EigenvalueProblem::EigenvalueProblem}

template <int dim>
EigenvalueProblem<dim>::EigenvalueProblem ()
		:
                fe (1),
		dof_handler (triangulation)
{
  parameters.declare_entry ("Number of eigenvalues/eigenfunctions", "10",
			    Patterns::Integer (0, 100),
			    "The number of eigenvalues/eigenfunctions "
			    "to be computed.");
  parameters.declare_entry ("Potential", "0",
			    Patterns::Anything(),
			    "A functional description of the potential.");
}

                                 // @sect4{EigenvalueProblem::make_grid_and_dofs}
template <int dim>
void EigenvalueProblem<dim>::make_grid_and_dofs ()
{
  GridGenerator::hyper_cube (triangulation, -1, 1);
  triangulation.refine_global (4);
  dof_handler.distribute_dofs (fe);

  CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
				       dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern (dof_handler, csp);
  stiffness_matrix.reinit (csp);
  mass_matrix.reinit (csp);

  eigenfunctions
    .resize (parameters.get_integer ("Number of eigenvalues/eigenfunctions"));
  for (unsigned int i=0; i<eigenfunctions.size(); ++i)
    eigenfunctions[i].reinit (dof_handler.n_dofs());
}

                                 // @sect4{EigenvalueProblem::assemble_system}
template <int dim>
void EigenvalueProblem<dim>::assemble_system ()
{
  QGauss<dim>  quadrature_formula(2);

  FEValues<dim> fe_values (fe, quadrature_formula,
			   update_values   | update_gradients |
                           update_JxW_values);

  const unsigned int dofs_per_cell = fe.dofs_per_cell;
  const unsigned int n_q_points    = quadrature_formula.size();

  FullMatrix<double> cell_stiffness_matrix (dofs_per_cell, dofs_per_cell);
  FullMatrix<double> cell_mass_matrix (dofs_per_cell, dofs_per_cell);

  std::vector<unsigned int> local_dof_indices (dofs_per_cell);

  FunctionParser<dim> potential;
  potential.initialize ((dim == 2 ?
			 "x,y" :
			 "x,y,z"),
			parameters.get ("Potential"),
			typename FunctionParser<dim>::ConstMap());

  ConstraintMatrix constraints;
  VectorTools::interpolate_boundary_values (dof_handler,
					    0,
					    ZeroFunction<dim>(),
					    constraints);

  typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
  for (; cell!=endc; ++cell)
    {
      fe_values.reinit (cell);
      cell_stiffness_matrix = 0;
      cell_mass_matrix = 0;

      for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	for (unsigned int i=0; i<dofs_per_cell; ++i)
	  for (unsigned int j=0; j<dofs_per_cell; ++j)
	    {
	      cell_stiffness_matrix(i,j)
		+= (fe_values.shape_grad (i, q_point) *
		    fe_values.shape_grad (j, q_point) *
		    fe_values.JxW (q_point));
	      cell_mass_matrix(i,j)
		+= (fe_values.shape_value (i, q_point) *
		    fe_values.shape_value (j, q_point) *
		    fe_values.JxW (q_point));
	    }

      cell->get_dof_indices (local_dof_indices);

      constraints.distribute_local_to_global (cell_stiffness_matrix,
					      local_dof_indices,
					      stiffness_matrix);
      constraints.distribute_local_to_global (cell_mass_matrix,
					      local_dof_indices,
					      mass_matrix);
    }
}

                                 // @sect4{EigenvalueProblem::solve}
template <int dim>
void EigenvalueProblem<dim>::solve ()
{
// do whatever is necessary here
}

                                 // @sect4{EigenvalueProblem::output_results}

template <int dim>
void EigenvalueProblem<dim>::output_results () const
{
// do whatever is necessary here
}

                                 // @sect4{EigenvalueProblem::run}

                                 // This is the function which has the
				 // top-level control over everything. It is
				 // the same as for the previous example.
template <int dim>
void EigenvalueProblem<dim>::run ()
{
  std::cout << "Solving problem in " << dim << " space dimensions." << std::endl;

  make_grid_and_dofs();
  assemble_system ();
  solve ();
  output_results ();
}

                                 // @sect3{The main function}

int main ()
{
  try
    {
      deallog.depth_console (0);
      EigenvalueProblem<2> laplace_problem_2d;
      laplace_problem_2d.run ();
    }
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      std::cerr << "Exception on processing: " << std::endl
		<< exc.what() << std::endl
		<< "Aborting!" << std::endl
		<< "----------------------------------------------------"
		<< std::endl;

      return 1;
    }
  catch (...)
    {
      std::cerr << std::endl << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      std::cerr << "Unknown exception!" << std::endl
		<< "Aborting!" << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      return 1;
    }

  return 0;
}
<commit_msg>Write the output_results() function.<commit_after>/* $Id$ */
/* Author: Toby Young, Polish Academy of Sciences,                */
/*         Wolfgang Bangerth, Texas A&M University                */
/*    $Id$        */
/*                                                                */
/*    Copyright (C) 2009 by the deal.II authors */
/*                                                                */
/*    This file is subject to QPL and may not be  distributed     */
/*    without copyright and license information. Please refer     */
/*    to the file deal.II/doc/license.html for the  text  and     */
/*    further information on this license.                        */

                                 // @sect3{Include files}

#include <base/logstream.h>
#include <base/quadrature_lib.h>
#include <base/function.h>
#include <base/function_parser.h>
#include <base/parameter_handler.h>
#include <base/utilities.h>
#include <lac/full_matrix.h>
#include <lac/petsc_sparse_matrix.h>
#include <lac/petsc_vector.h>
#include <lac/solver_cg.h>
#include <lac/precondition.h>
#include <lac/compressed_simple_sparsity_pattern.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
#include <fe/fe_q.h>
#include <fe/fe_values.h>
#include <numerics/vectors.h>
#include <numerics/matrices.h>
#include <numerics/data_out.h>

#include <fstream>
#include <iostream>

				 // The final step, as in previous
				 // programs, is to import all the
				 // deal.II class and function names
				 // into the global namespace:
using namespace dealii;

                                 // @sect3{The EigenvalueProblem class template}

template <int dim>
class EigenvalueProblem
{
  public:
    EigenvalueProblem ();
    void run ();

  private:
    void make_grid_and_dofs ();
    void assemble_system ();
    void solve ();
    void output_results () const;

    Triangulation<dim>   triangulation;
    FE_Q<dim>            fe;
    DoFHandler<dim>      dof_handler;

    PETScWrappers::SparseMatrix        stiffness_matrix, mass_matrix;
    std::vector<PETScWrappers::Vector> eigenfunctions;

    ParameterHandler parameters;
};

                                 // @sect3{Implementation of the EigenvalueProblem class}

                                 // @sect4{EigenvalueProblem::EigenvalueProblem}

template <int dim>
EigenvalueProblem<dim>::EigenvalueProblem ()
		:
                fe (1),
		dof_handler (triangulation)
{
  parameters.declare_entry ("Number of eigenvalues/eigenfunctions", "10",
			    Patterns::Integer (0, 100),
			    "The number of eigenvalues/eigenfunctions "
			    "to be computed.");
  parameters.declare_entry ("Potential", "0",
			    Patterns::Anything(),
			    "A functional description of the potential.");
}

                                 // @sect4{EigenvalueProblem::make_grid_and_dofs}
template <int dim>
void EigenvalueProblem<dim>::make_grid_and_dofs ()
{
  GridGenerator::hyper_cube (triangulation, -1, 1);
  triangulation.refine_global (4);
  dof_handler.distribute_dofs (fe);

  CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
				       dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern (dof_handler, csp);
  stiffness_matrix.reinit (csp);
  mass_matrix.reinit (csp);

  eigenfunctions
    .resize (parameters.get_integer ("Number of eigenvalues/eigenfunctions"));
  for (unsigned int i=0; i<eigenfunctions.size(); ++i)
    eigenfunctions[i].reinit (dof_handler.n_dofs());
}

                                 // @sect4{EigenvalueProblem::assemble_system}
template <int dim>
void EigenvalueProblem<dim>::assemble_system ()
{
  QGauss<dim>  quadrature_formula(2);

  FEValues<dim> fe_values (fe, quadrature_formula,
			   update_values   | update_gradients |
                           update_JxW_values);

  const unsigned int dofs_per_cell = fe.dofs_per_cell;
  const unsigned int n_q_points    = quadrature_formula.size();

  FullMatrix<double> cell_stiffness_matrix (dofs_per_cell, dofs_per_cell);
  FullMatrix<double> cell_mass_matrix (dofs_per_cell, dofs_per_cell);

  std::vector<unsigned int> local_dof_indices (dofs_per_cell);

  FunctionParser<dim> potential;
  potential.initialize ((dim == 2 ?
			 "x,y" :
			 "x,y,z"),
			parameters.get ("Potential"),
			typename FunctionParser<dim>::ConstMap());

  ConstraintMatrix constraints;
  VectorTools::interpolate_boundary_values (dof_handler,
					    0,
					    ZeroFunction<dim>(),
					    constraints);

  typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
  for (; cell!=endc; ++cell)
    {
      fe_values.reinit (cell);
      cell_stiffness_matrix = 0;
      cell_mass_matrix = 0;

      for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	for (unsigned int i=0; i<dofs_per_cell; ++i)
	  for (unsigned int j=0; j<dofs_per_cell; ++j)
	    {
	      cell_stiffness_matrix(i,j)
		+= (fe_values.shape_grad (i, q_point) *
		    fe_values.shape_grad (j, q_point) *
		    fe_values.JxW (q_point));
	      cell_mass_matrix(i,j)
		+= (fe_values.shape_value (i, q_point) *
		    fe_values.shape_value (j, q_point) *
		    fe_values.JxW (q_point));
	    }

      cell->get_dof_indices (local_dof_indices);

      constraints.distribute_local_to_global (cell_stiffness_matrix,
					      local_dof_indices,
					      stiffness_matrix);
      constraints.distribute_local_to_global (cell_mass_matrix,
					      local_dof_indices,
					      mass_matrix);
    }
}

                                 // @sect4{EigenvalueProblem::solve}
template <int dim>
void EigenvalueProblem<dim>::solve ()
{
// do whatever is necessary here
}

                                 // @sect4{EigenvalueProblem::output_results}

template <int dim>
void EigenvalueProblem<dim>::output_results () const
{
  DataOut<dim> data_out;

  data_out.attach_dof_handler (dof_handler);

  for (unsigned int i=0; i<eigenfunctions.size(); ++i)
    data_out.add_data_vector (eigenfunctions[i],
			      std::string("solution") +
			      Utilities::int_to_string(i));

  data_out.build_patches ();

  std::ofstream output ("eigenvectors.vtk");
  data_out.write_vtk (output);
}

                                 // @sect4{EigenvalueProblem::run}

                                 // This is the function which has the
				 // top-level control over everything. It is
				 // the same as for the previous example.
template <int dim>
void EigenvalueProblem<dim>::run ()
{
  std::cout << "Solving problem in " << dim << " space dimensions." << std::endl;

  make_grid_and_dofs();
  assemble_system ();
  solve ();
  output_results ();
}

                                 // @sect3{The main function}

int main ()
{
  try
    {
      deallog.depth_console (0);
      EigenvalueProblem<2> laplace_problem_2d;
      laplace_problem_2d.run ();
    }
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      std::cerr << "Exception on processing: " << std::endl
		<< exc.what() << std::endl
		<< "Aborting!" << std::endl
		<< "----------------------------------------------------"
		<< std::endl;

      return 1;
    }
  catch (...)
    {
      std::cerr << std::endl << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      std::cerr << "Unknown exception!" << std::endl
		<< "Aborting!" << std::endl
		<< "----------------------------------------------------"
		<< std::endl;
      return 1;
    }

  return 0;
}
<|endoftext|>


<commit_before>#include "advertisement.hpp"

#include <limits>
#include <iostream>
#include <sstream>
#include <netinet/in.h>

#include <node.h>

namespace node_mdns {

using namespace v8;

Persistent<String> Advertisement::name_symbol;
Persistent<String> Advertisement::regtype_symbol;
Persistent<String> Advertisement::domain_symbol;

struct AdContext {
    AdContext(Local<Object> const& this_, Local<Value> const& callback) :
        this_(Persistent<Object>::New(this_)),
        callback(Persistent<Function>::New(Local<Function>::Cast(callback)))
        {}
    ~AdContext() { callback.Dispose(); this_.Dispose(); }

    Persistent<Object>   this_;
    Persistent<Function> callback;
};

void
Advertisement::Initialize(Handle<Object> target) {
    HandleScope scope;
    Local<FunctionTemplate> t = mDNSBase::Initialize(target, New);

    name_symbol = NODE_PSYMBOL("name");
    regtype_symbol = NODE_PSYMBOL("regtype");
    domain_symbol = NODE_PSYMBOL("domain");

    NODE_SET_PROTOTYPE_METHOD(t, "doStart", DoStart);

    target->Set(String::NewSymbol("Advertisement"), t->GetFunction());
}

Handle<Value>
Advertisement::DoStart(DNSServiceFlags flags, uint32_t interface_index,
        const char * name, const char * regtype, const char * domain,
        const char * host, uint16_t port, Handle<Value> const& txt_record_object,
        AdContext * context)
{
    if (ServiceRef()) {
        return ThrowException(Exception::Error(
                   String::New("Advertisement already started.")));
    }

    if ( ! txt_record_object->IsUndefined()) {
        Local<Array> props = txt_record_object->ToObject()->GetPropertyNames();
        for (size_t i = 0; i < props->Length(); ++i) {
            String::Utf8Value key( props->Get(i)->ToString() );
            std::cout << "===" << *key << std::endl;
            Handle<Value> value = txt_record_object->ToObject()->Get(props->Get(i));
            if (value->IsString()) {
                std::cout << "string" << std::endl;
                String::Utf8Value string_value( value->ToString());
                std::cout << "string a" << std::endl;
                //TXTRecordSetValue( & txt_record_, *key, 0, NULL);
                TXTRecordSetValue( &txt_record_, *key, value->ToString()->Utf8Length(), *string_value);
                std::cout << "string b" << std::endl;
            }/* TODO: else if (node::Buffer::HasInstance(value)) {
                std::cout << "buffer" << std::endl;
            }*/
        }
    }
    uint16_t txt_record_length = TXTRecordGetLength( & txt_record_);
    const void * txt_record_ptr = txt_record_length ? TXTRecordGetBytesPtr( & txt_record_) : NULL;

    int status = DNSServiceRegister( & ServiceRef(), flags, interface_index,
            name, regtype, domain, host, port, txt_record_length,
            txt_record_ptr, & on_service_registered, context);
    if (kDNSServiceErr_NoError != status) {
        return ThrowException(buildException(status));
    }

    Handle<Value> result = prepareSocket();
    if ( ! result->IsUndefined()) {
        return ThrowException(result);
    }

    Ref();

    return Undefined();
}

Handle<Value>
Advertisement::New(const Arguments & args) {
    HandleScope scope;

    Advertisement * ad = new Advertisement();
    ad->Wrap(args.This());
    return args.This();
}

Advertisement::Advertisement() : mDNSBase() {
    TXTRecordCreate(& txt_record_, TXT_RECORD_BUFFER_SIZE, txt_record_buffer_);
}

Advertisement::~Advertisement() {
    TXTRecordDeallocate( & txt_record_);
}

void
Advertisement::on_service_registered(DNSServiceFlags flags,
        DNSServiceErrorType errorCode, const char * name,
        const char * regtype, const char * domain, AdContext * context)
{
    size_t argc = 3;
    Local<Value> args[3];
    if (kDNSServiceErr_NoError == errorCode) {
        Local<Object> info = Object::New();
        info->Set(name_symbol, String::New(name));
        info->Set(regtype_symbol, String::New(regtype));
        info->Set(domain_symbol, String::New(domain));

        args[0] = Local<Value>::New(Null());
        args[1] = info;
        args[2] = Integer::New(flags);
        argc = 3;
    } else {
        args[0] = buildException(errorCode);
        argc = 1;
    }
    context->callback->Call(context->this_, argc, args);
    delete context;
}

Handle<Value>
Advertisement::DoStart(const Arguments & args) {
    HandleScope scope;
    Advertisement * ad = ObjectWrap::Unwrap<Advertisement>(args.This());

    std::ostringstream msg;
    if ( 9 != args.Length()) {
        msg << "argument mismatch. expected 9 but got " << args.Length();
        return ThrowException(Exception::Error(
                String::New(msg.str().c_str())));
    }

    DNSServiceFlags flags;
    if ( args[0]->IsUndefined()) {
        flags = 0;
    } else if (args[0]->IsInt32()) {
        flags = args[0]->ToInteger()->Int32Value();
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 0 must be an integer")));
    }

    uint32_t interface_index;
    if (args[1]->IsUndefined()) {
        interface_index = 0;
    } else if (args[1]->IsInt32()) {
        interface_index = args[1]->ToInteger()->Int32Value();
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 1 must be an integer")));
    }

    std::string name;
    if (args[2]->IsUndefined()) {
        // nothing to do
    } else if (args[2]->IsString()) {
        name = *String::Utf8Value(args[2]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 2 must be a string")));
    }

    if ( ! args[3]->IsString()) {
        return ThrowException(Exception::TypeError(
                    String::New("argument 3 must be a string")));
    }
    String::Utf8Value regtype(args[3]->ToString());

    std::string domain;
    if (args[4]->IsUndefined()) {
        // nothing to do
    } else if (args[4]->IsString()) {
        domain = *String::Utf8Value(args[4]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 4 must be a string.")));
    }

    std::string host;
    if (args[5]->IsUndefined()) {
        // nothing to do
    } else if (args[5]->IsString()) {
        host = *String::Utf8Value(args[5]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 5 must be a string")));
    }

    if ( ! args[6]->IsInt32()) {
        return ThrowException(Exception::TypeError(
                    String::New("argument 6 must be an integer")));
    }
    int raw_port = args[6]->ToInteger()->Int32Value();
    if (std::numeric_limits<uint16_t>::max() < raw_port ||
        0 > raw_port)
    {
        return ThrowException(Exception::TypeError(
                String::New("argument 6: illegal port number.")));
    }
    uint16_t port = static_cast<uint16_t>(htons(raw_port));

    Handle<Value> txt_record = Undefined();
    if ( ! args[7]->IsUndefined()) {
        if ( ! args[7]->IsObject()) {
            return ThrowException(Exception::TypeError(
                        String::New("argument 7 must be an object.")));
        }
        txt_record = args[7]->ToObject();
    }

    if ( ! args[8]->IsFunction()) {
        return ThrowException(Exception::TypeError(
                String::New("argument 8 must be a function")));
    }
    AdContext * ctx = new AdContext(args.This(), args[8]);

    Handle<Value> result = ad->DoStart(flags, interface_index,
            name.empty() ? NULL : name.c_str(),
            *regtype,
            domain.empty() ? NULL : domain.c_str(),
            host.empty() ? NULL : host.c_str(),
            port, txt_record, ctx);

    if (! result->IsUndefined()) {
        return ThrowException(result);
    }
    return Undefined();
}

void
Advertisement::on_service_registered(DNSServiceRef /*sdRef*/, DNSServiceFlags flags,
        DNSServiceErrorType errorCode, const char *name,
        const char *regtype, const char *domain, void *context )
{
    AdContext * ctx = static_cast<AdContext*>(context);
    Advertisement * ad = ObjectWrap::Unwrap<Advertisement>(ctx->this_);
    ad->on_service_registered(flags, errorCode, name, regtype, domain, ctx);
}

} // end of namespace node_mdns
<commit_msg>removed debug output<commit_after>#include "advertisement.hpp"

#include <limits>
#include <iostream>
#include <sstream>
#include <netinet/in.h>

#include <node.h>

namespace node_mdns {

using namespace v8;

Persistent<String> Advertisement::name_symbol;
Persistent<String> Advertisement::regtype_symbol;
Persistent<String> Advertisement::domain_symbol;

struct AdContext {
    AdContext(Local<Object> const& this_, Local<Value> const& callback) :
        this_(Persistent<Object>::New(this_)),
        callback(Persistent<Function>::New(Local<Function>::Cast(callback)))
        {}
    ~AdContext() { callback.Dispose(); this_.Dispose(); }

    Persistent<Object>   this_;
    Persistent<Function> callback;
};

void
Advertisement::Initialize(Handle<Object> target) {
    HandleScope scope;
    Local<FunctionTemplate> t = mDNSBase::Initialize(target, New);

    name_symbol = NODE_PSYMBOL("name");
    regtype_symbol = NODE_PSYMBOL("regtype");
    domain_symbol = NODE_PSYMBOL("domain");

    NODE_SET_PROTOTYPE_METHOD(t, "doStart", DoStart);

    target->Set(String::NewSymbol("Advertisement"), t->GetFunction());
}

Handle<Value>
Advertisement::DoStart(DNSServiceFlags flags, uint32_t interface_index,
        const char * name, const char * regtype, const char * domain,
        const char * host, uint16_t port, Handle<Value> const& txt_record_object,
        AdContext * context)
{
    if (ServiceRef()) {
        return ThrowException(Exception::Error(
                   String::New("Advertisement already started.")));
    }

    if ( ! txt_record_object->IsUndefined()) {
        Local<Array> props = txt_record_object->ToObject()->GetPropertyNames();
        for (size_t i = 0; i < props->Length(); ++i) {
            String::Utf8Value key( props->Get(i)->ToString() );
            Handle<Value> value = txt_record_object->ToObject()->Get(props->Get(i));
            if (value->IsString()) {
                String::Utf8Value string_value( value->ToString());
                TXTRecordSetValue( &txt_record_, *key, value->ToString()->Utf8Length(), *string_value);
            }/* TODO: else if (node::Buffer::HasInstance(value)) {
                std::cout << "buffer" << std::endl;
            }*/
        }
    }
    uint16_t txt_record_length = TXTRecordGetLength( & txt_record_);
    const void * txt_record_ptr = txt_record_length ? TXTRecordGetBytesPtr( & txt_record_) : NULL;

    int status = DNSServiceRegister( & ServiceRef(), flags, interface_index,
            name, regtype, domain, host, port, txt_record_length,
            txt_record_ptr, & on_service_registered, context);
    if (kDNSServiceErr_NoError != status) {
        return ThrowException(buildException(status));
    }

    Handle<Value> result = prepareSocket();
    if ( ! result->IsUndefined()) {
        return ThrowException(result);
    }

    Ref();

    return Undefined();
}

Handle<Value>
Advertisement::New(const Arguments & args) {
    HandleScope scope;

    Advertisement * ad = new Advertisement();
    ad->Wrap(args.This());
    return args.This();
}

Advertisement::Advertisement() : mDNSBase() {
    TXTRecordCreate(& txt_record_, TXT_RECORD_BUFFER_SIZE, txt_record_buffer_);
}

Advertisement::~Advertisement() {
    TXTRecordDeallocate( & txt_record_);
}

void
Advertisement::on_service_registered(DNSServiceFlags flags,
        DNSServiceErrorType errorCode, const char * name,
        const char * regtype, const char * domain, AdContext * context)
{
    size_t argc = 3;
    Local<Value> args[3];
    if (kDNSServiceErr_NoError == errorCode) {
        Local<Object> info = Object::New();
        info->Set(name_symbol, String::New(name));
        info->Set(regtype_symbol, String::New(regtype));
        info->Set(domain_symbol, String::New(domain));

        args[0] = Local<Value>::New(Null());
        args[1] = info;
        args[2] = Integer::New(flags);
        argc = 3;
    } else {
        args[0] = buildException(errorCode);
        argc = 1;
    }
    context->callback->Call(context->this_, argc, args);
    delete context;
}

Handle<Value>
Advertisement::DoStart(const Arguments & args) {
    HandleScope scope;
    Advertisement * ad = ObjectWrap::Unwrap<Advertisement>(args.This());

    std::ostringstream msg;
    if ( 9 != args.Length()) {
        msg << "argument mismatch. expected 9 but got " << args.Length();
        return ThrowException(Exception::Error(
                String::New(msg.str().c_str())));
    }

    DNSServiceFlags flags;
    if ( args[0]->IsUndefined()) {
        flags = 0;
    } else if (args[0]->IsInt32()) {
        flags = args[0]->ToInteger()->Int32Value();
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 0 must be an integer")));
    }

    uint32_t interface_index;
    if (args[1]->IsUndefined()) {
        interface_index = 0;
    } else if (args[1]->IsInt32()) {
        interface_index = args[1]->ToInteger()->Int32Value();
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 1 must be an integer")));
    }

    std::string name;
    if (args[2]->IsUndefined()) {
        // nothing to do
    } else if (args[2]->IsString()) {
        name = *String::Utf8Value(args[2]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 2 must be a string")));
    }

    if ( ! args[3]->IsString()) {
        return ThrowException(Exception::TypeError(
                    String::New("argument 3 must be a string")));
    }
    String::Utf8Value regtype(args[3]->ToString());

    std::string domain;
    if (args[4]->IsUndefined()) {
        // nothing to do
    } else if (args[4]->IsString()) {
        domain = *String::Utf8Value(args[4]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 4 must be a string.")));
    }

    std::string host;
    if (args[5]->IsUndefined()) {
        // nothing to do
    } else if (args[5]->IsString()) {
        host = *String::Utf8Value(args[5]->ToString());
    } else {
        return ThrowException(Exception::TypeError(
                    String::New("argument 5 must be a string")));
    }

    if ( ! args[6]->IsInt32()) {
        return ThrowException(Exception::TypeError(
                    String::New("argument 6 must be an integer")));
    }
    int raw_port = args[6]->ToInteger()->Int32Value();
    if (std::numeric_limits<uint16_t>::max() < raw_port ||
        0 > raw_port)
    {
        return ThrowException(Exception::TypeError(
                String::New("argument 6: illegal port number.")));
    }
    uint16_t port = static_cast<uint16_t>(htons(raw_port));

    Handle<Value> txt_record = Undefined();
    if ( ! args[7]->IsUndefined()) {
        if ( ! args[7]->IsObject()) {
            return ThrowException(Exception::TypeError(
                        String::New("argument 7 must be an object.")));
        }
        txt_record = args[7]->ToObject();
    }

    if ( ! args[8]->IsFunction()) {
        return ThrowException(Exception::TypeError(
                String::New("argument 8 must be a function")));
    }
    AdContext * ctx = new AdContext(args.This(), args[8]);

    Handle<Value> result = ad->DoStart(flags, interface_index,
            name.empty() ? NULL : name.c_str(),
            *regtype,
            domain.empty() ? NULL : domain.c_str(),
            host.empty() ? NULL : host.c_str(),
            port, txt_record, ctx);

    if (! result->IsUndefined()) {
        return ThrowException(result);
    }
    return Undefined();
}

void
Advertisement::on_service_registered(DNSServiceRef /*sdRef*/, DNSServiceFlags flags,
        DNSServiceErrorType errorCode, const char *name,
        const char *regtype, const char *domain, void *context )
{
    AdContext * ctx = static_cast<AdContext*>(context);
    Advertisement * ad = ObjectWrap::Unwrap<Advertisement>(ctx->this_);
    ad->on_service_registered(flags, errorCode, name, regtype, domain, ctx);
}

} // end of namespace node_mdns
<|endoftext|>


<commit_before>#include "capstone_wrapper.h"
#include <windows.h>

csh Capstone::mHandle = 0;
bool Capstone::mInitialized = false;

void Capstone::GlobalInitialize()
{
    if(!mInitialized)
    {
        mInitialized = true;
#ifdef _WIN64
        cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
        cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
        cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
    }
}

void Capstone::GlobalFinalize()
{
    if(mHandle) //close handle
        cs_close(&mHandle);
    mInitialized = false;
}

Capstone::Capstone()
{
    GlobalInitialize();
    mInstr = cs_malloc(mHandle);
    mSuccess = false;
}

Capstone::Capstone(const Capstone & capstone)
    : mInstr(cs_malloc(mHandle)),
      mSuccess(false)
{
}

Capstone::~Capstone()
{
    if(mInstr) //free last disassembled instruction
        cs_free(mInstr, 1);
}

bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
    return Disassemble(addr, data, MAX_DISASM_BUFFER);
}

bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
    if(!data || !size)
        return false;

    size_t codeSize = size;
    uint64_t addr64 = addr;

    return (mSuccess = cs_disasm_iter(mHandle, &data, &codeSize, &addr64, mInstr));
}

bool Capstone::DisassembleSafe(size_t addr, const unsigned char* data, int size)
{
    unsigned char dataSafe[MAX_DISASM_BUFFER];
    memset(dataSafe, 0, sizeof(dataSafe));
    memcpy(dataSafe, data, min(MAX_DISASM_BUFFER, size));
    return Disassemble(addr, dataSafe);
}

const cs_insn* Capstone::GetInstr() const
{
    if(!Success())
        return nullptr;
    return mInstr;
}

bool Capstone::Success() const
{
    return mSuccess;
}

const char* Capstone::RegName(x86_reg reg) const
{
    return cs_reg_name(mHandle, reg);
}

bool Capstone::InGroup(cs_group_type group) const
{
    if(!Success())
        return false;
    if(group == CS_GRP_PRIVILEGE)
    {
        auto id = GetId();
        // I/O instructions
        if(id == X86_INS_OUT || id == X86_INS_OUTSB || id == X86_INS_OUTSD || id == X86_INS_OUTSW
                || id == X86_INS_IN || id == X86_INS_INSB || id == X86_INS_INSD || id == X86_INS_INSW
                // system instructions
                || id == X86_INS_RDMSR || id == X86_INS_SMSW)
            return true;
    }
    return cs_insn_group(mHandle, mInstr, group);
}

std::string Capstone::OperandText(int opindex) const
{
    if(!Success() || opindex >= mInstr->detail->x86.op_count)
        return "";
    const auto & op = mInstr->detail->x86.operands[opindex];
    std::string result;
    char temp[32] = "";
    switch(op.type)
    {
    case X86_OP_REG:
    {
        result = RegName(x86_reg(op.reg));
    }
    break;

    case X86_OP_IMM:
    {
        sprintf_s(temp, "%llX", op.imm);
        result = temp;
    }
    break;

    case X86_OP_MEM:
    {
        const auto & mem = op.mem;
        if(op.mem.base == X86_REG_RIP)  //rip-relative
        {
            sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
            result += temp;
        }
        else //normal
        {
            bool prependPlus = false;
            if(mem.base)
            {
                result += RegName(x86_reg(mem.base));
                prependPlus = true;
            }
            if(mem.index)
            {
                if(prependPlus)
                    result += "+";
                result += RegName(x86_reg(mem.index));
                sprintf_s(temp, "*%X", mem.scale);
                result += temp;
                prependPlus = true;
            }
            if(mem.disp)
            {
                char operatorText = '+';
                if(mem.disp < 0)
                {
                    operatorText = '-';
                    sprintf_s(temp, "%llX", mem.disp * -1);
                }
                else
                    sprintf_s(temp, "%llX", mem.disp);
                if(prependPlus)
                    result += operatorText;
                result += temp;
            }
        }
    }
    break;

    case X86_OP_INVALID:
    {
    }
    break;
    }
    return result;
}

int Capstone::Size() const
{
    if(!Success())
        return 1;
    return GetInstr()->size;
}

size_t Capstone::Address() const
{
    if(!Success())
        return 0;
    return size_t(GetInstr()->address);
}

const cs_x86 & Capstone::x86() const
{
    if(!Success())
        DebugBreak();
    return GetInstr()->detail->x86;
}

bool Capstone::IsFilling() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_INT3:
        return true;
    default:
        return false;
    }
}

bool Capstone::IsLoop() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        return true;
    default:
        return false;
    }
}

x86_insn Capstone::GetId() const
{
    if(!Success())
        DebugBreak();
    return x86_insn(mInstr->id);
}

std::string Capstone::InstructionText() const
{
    if(!Success())
        return "???";
    std::string result = Mnemonic();
    if(OpCount())
    {
        result += " ";
        result += mInstr->op_str;
    }
    return result;
}

int Capstone::OpCount() const
{
    if(!Success())
        return 0;
    return x86().op_count;
}

const cs_x86_op & Capstone::operator[](int index) const
{
    if(!Success() || index < 0 || index >= OpCount())
        DebugBreak();
    return x86().operands[index];
}

bool Capstone::IsNop() const
{
    if(!Success())
        return false;
    const auto & ops = x86().operands;
    cs_x86_op op;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_PAUSE:
    case X86_INS_FNOP:
        // nop
        return true;
    case X86_INS_MOV:
    case X86_INS_CMOVA:
    case X86_INS_CMOVAE:
    case X86_INS_CMOVB:
    case X86_INS_CMOVBE:
    case X86_INS_CMOVE:
    case X86_INS_CMOVNE:
    case X86_INS_CMOVG:
    case X86_INS_CMOVGE:
    case X86_INS_CMOVL:
    case X86_INS_CMOVLE:
    case X86_INS_CMOVO:
    case X86_INS_CMOVNO:
    case X86_INS_CMOVP:
    case X86_INS_CMOVNP:
    case X86_INS_CMOVS:
    case X86_INS_CMOVNS:
    case X86_INS_MOVAPS:
    case X86_INS_MOVAPD:
    case X86_INS_MOVUPS:
    case X86_INS_MOVUPD:
    case X86_INS_XCHG:
        // mov edi, edi
        return ops[0].type == X86_OP_REG && ops[1].type == X86_OP_REG && ops[0].reg == ops[1].reg;
    case X86_INS_LEA:
    {
        // lea eax, [eax + 0]
        auto reg = ops[0].reg;
        auto mem = ops[1].mem;
        return ops[0].type == X86_OP_REG && ops[1].type == X86_OP_MEM && mem.disp == 0 &&
            ((mem.index == X86_REG_INVALID && mem.base == reg) ||
            (mem.index == reg && mem.base == X86_REG_INVALID && mem.scale == 1));
    }
    case X86_INS_JMP:
    case X86_INS_JA:
    case X86_INS_JAE:
    case X86_INS_JB:
    case X86_INS_JBE:
    case X86_INS_JE:
    case X86_INS_JNE:
    case X86_INS_JG:
    case X86_INS_JGE:
    case X86_INS_JL:
    case X86_INS_JLE:
    case X86_INS_JO:
    case X86_INS_JNO:
    case X86_INS_JP:
    case X86_INS_JNP:
    case X86_INS_JS:
    case X86_INS_JNS:
    case X86_INS_JECXZ:
    case X86_INS_JCXZ:
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        // jmp 0
        op = ops[0];
        return op.type == X86_OP_IMM && op.imm == 0;
    case X86_INS_SHL:
    case X86_INS_SHR:
    case X86_INS_ROL:
    case X86_INS_ROR:
    case X86_INS_SAR:
    case X86_INS_SAL:
    case X86_INS_SHLD:
    case X86_INS_SHRD:
        // shl eax, 0
        op = ops[OpCount() - 1];
        return op.type == X86_OP_IMM && op.imm == 0;
    default:
        return false;
    }
}

bool Capstone::IsInt3() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_INT3:
        return true;
    case X86_INS_INT:
    {
        cs_x86_op op = x86().operands[0];
        return op.type == X86_OP_IMM && op.imm == 3;
    }
    default:
        return false;
    }
}

bool Capstone::IsUnusual() const
{
    auto id = GetId();
    return (InGroup(CS_GRP_PRIVILEGE) || InGroup(CS_GRP_IRET) || InGroup(CS_GRP_INVALID)
            || id == X86_INS_RDTSC || id == X86_INS_SYSCALL || id == X86_INS_SYSENTER || id == X86_INS_CPUID || id == X86_INS_RDTSCP
            || id == X86_INS_RDRAND || id == X86_INS_RDSEED);
}

std::string Capstone::Mnemonic() const
{
    if(!Success())
        return "???";
    return mInstr->mnemonic;
}

std::string Capstone::MnemonicId() const
{
    if(!Success())
        return "???";
    return cs_insn_name(mHandle, GetId());
}

const char* Capstone::MemSizeName(int size) const
{
    switch(size)
    {
    case 1:
        return "byte";
    case 2:
        return "word";
    case 4:
        return "dword";
    case 6:
        return "fword";
    case 8:
        return "qword";
    case 10:
        return "tword";
    case 16:
        return "dqword";
    case 32:
        return "yword";
    case 64:
        return "zword";
    default:
        return nullptr;
    }
}

size_t Capstone::BranchDestination() const
{
    if(!Success())
        return 0;
    if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
    {
        const auto & op = x86().operands[0];
        if(op.type == CS_OP_IMM)
            return size_t(op.imm);
    }
    return 0;
}

size_t Capstone::ResolveOpValue(int opindex, const std::function<size_t(x86_reg)> & resolveReg) const
{
    size_t dest = 0;
    const auto & op = x86().operands[opindex];
    switch(op.type)
    {
    case X86_OP_IMM:
        dest = size_t(op.imm);
        break;
    case X86_OP_REG:
        dest = resolveReg(op.reg);
        break;
    case X86_OP_MEM:
        dest = size_t(op.mem.disp);
        if(op.mem.base == X86_REG_RIP) //rip-relative
            dest += Address() + Size();
        else
            dest += resolveReg(op.mem.base) + resolveReg(op.mem.index) * op.mem.scale;
        break;
    default:
        break;
    }
    return dest;
}
<commit_msg>AStyle<commit_after>#include "capstone_wrapper.h"
#include <windows.h>

csh Capstone::mHandle = 0;
bool Capstone::mInitialized = false;

void Capstone::GlobalInitialize()
{
    if(!mInitialized)
    {
        mInitialized = true;
#ifdef _WIN64
        cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
        cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
        cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
    }
}

void Capstone::GlobalFinalize()
{
    if(mHandle) //close handle
        cs_close(&mHandle);
    mInitialized = false;
}

Capstone::Capstone()
{
    GlobalInitialize();
    mInstr = cs_malloc(mHandle);
    mSuccess = false;
}

Capstone::Capstone(const Capstone & capstone)
    : mInstr(cs_malloc(mHandle)),
      mSuccess(false)
{
}

Capstone::~Capstone()
{
    if(mInstr) //free last disassembled instruction
        cs_free(mInstr, 1);
}

bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
    return Disassemble(addr, data, MAX_DISASM_BUFFER);
}

bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
    if(!data || !size)
        return false;

    size_t codeSize = size;
    uint64_t addr64 = addr;

    return (mSuccess = cs_disasm_iter(mHandle, &data, &codeSize, &addr64, mInstr));
}

bool Capstone::DisassembleSafe(size_t addr, const unsigned char* data, int size)
{
    unsigned char dataSafe[MAX_DISASM_BUFFER];
    memset(dataSafe, 0, sizeof(dataSafe));
    memcpy(dataSafe, data, min(MAX_DISASM_BUFFER, size));
    return Disassemble(addr, dataSafe);
}

const cs_insn* Capstone::GetInstr() const
{
    if(!Success())
        return nullptr;
    return mInstr;
}

bool Capstone::Success() const
{
    return mSuccess;
}

const char* Capstone::RegName(x86_reg reg) const
{
    return cs_reg_name(mHandle, reg);
}

bool Capstone::InGroup(cs_group_type group) const
{
    if(!Success())
        return false;
    if(group == CS_GRP_PRIVILEGE)
    {
        auto id = GetId();
        // I/O instructions
        if(id == X86_INS_OUT || id == X86_INS_OUTSB || id == X86_INS_OUTSD || id == X86_INS_OUTSW
                || id == X86_INS_IN || id == X86_INS_INSB || id == X86_INS_INSD || id == X86_INS_INSW
                // system instructions
                || id == X86_INS_RDMSR || id == X86_INS_SMSW)
            return true;
    }
    return cs_insn_group(mHandle, mInstr, group);
}

std::string Capstone::OperandText(int opindex) const
{
    if(!Success() || opindex >= mInstr->detail->x86.op_count)
        return "";
    const auto & op = mInstr->detail->x86.operands[opindex];
    std::string result;
    char temp[32] = "";
    switch(op.type)
    {
    case X86_OP_REG:
    {
        result = RegName(x86_reg(op.reg));
    }
    break;

    case X86_OP_IMM:
    {
        sprintf_s(temp, "%llX", op.imm);
        result = temp;
    }
    break;

    case X86_OP_MEM:
    {
        const auto & mem = op.mem;
        if(op.mem.base == X86_REG_RIP)  //rip-relative
        {
            sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
            result += temp;
        }
        else //normal
        {
            bool prependPlus = false;
            if(mem.base)
            {
                result += RegName(x86_reg(mem.base));
                prependPlus = true;
            }
            if(mem.index)
            {
                if(prependPlus)
                    result += "+";
                result += RegName(x86_reg(mem.index));
                sprintf_s(temp, "*%X", mem.scale);
                result += temp;
                prependPlus = true;
            }
            if(mem.disp)
            {
                char operatorText = '+';
                if(mem.disp < 0)
                {
                    operatorText = '-';
                    sprintf_s(temp, "%llX", mem.disp * -1);
                }
                else
                    sprintf_s(temp, "%llX", mem.disp);
                if(prependPlus)
                    result += operatorText;
                result += temp;
            }
        }
    }
    break;

    case X86_OP_INVALID:
    {
    }
    break;
    }
    return result;
}

int Capstone::Size() const
{
    if(!Success())
        return 1;
    return GetInstr()->size;
}

size_t Capstone::Address() const
{
    if(!Success())
        return 0;
    return size_t(GetInstr()->address);
}

const cs_x86 & Capstone::x86() const
{
    if(!Success())
        DebugBreak();
    return GetInstr()->detail->x86;
}

bool Capstone::IsFilling() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_INT3:
        return true;
    default:
        return false;
    }
}

bool Capstone::IsLoop() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        return true;
    default:
        return false;
    }
}

x86_insn Capstone::GetId() const
{
    if(!Success())
        DebugBreak();
    return x86_insn(mInstr->id);
}

std::string Capstone::InstructionText() const
{
    if(!Success())
        return "???";
    std::string result = Mnemonic();
    if(OpCount())
    {
        result += " ";
        result += mInstr->op_str;
    }
    return result;
}

int Capstone::OpCount() const
{
    if(!Success())
        return 0;
    return x86().op_count;
}

const cs_x86_op & Capstone::operator[](int index) const
{
    if(!Success() || index < 0 || index >= OpCount())
        DebugBreak();
    return x86().operands[index];
}

bool Capstone::IsNop() const
{
    if(!Success())
        return false;
    const auto & ops = x86().operands;
    cs_x86_op op;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_PAUSE:
    case X86_INS_FNOP:
        // nop
        return true;
    case X86_INS_MOV:
    case X86_INS_CMOVA:
    case X86_INS_CMOVAE:
    case X86_INS_CMOVB:
    case X86_INS_CMOVBE:
    case X86_INS_CMOVE:
    case X86_INS_CMOVNE:
    case X86_INS_CMOVG:
    case X86_INS_CMOVGE:
    case X86_INS_CMOVL:
    case X86_INS_CMOVLE:
    case X86_INS_CMOVO:
    case X86_INS_CMOVNO:
    case X86_INS_CMOVP:
    case X86_INS_CMOVNP:
    case X86_INS_CMOVS:
    case X86_INS_CMOVNS:
    case X86_INS_MOVAPS:
    case X86_INS_MOVAPD:
    case X86_INS_MOVUPS:
    case X86_INS_MOVUPD:
    case X86_INS_XCHG:
        // mov edi, edi
        return ops[0].type == X86_OP_REG && ops[1].type == X86_OP_REG && ops[0].reg == ops[1].reg;
    case X86_INS_LEA:
    {
        // lea eax, [eax + 0]
        auto reg = ops[0].reg;
        auto mem = ops[1].mem;
        return ops[0].type == X86_OP_REG && ops[1].type == X86_OP_MEM && mem.disp == 0 &&
               ((mem.index == X86_REG_INVALID && mem.base == reg) ||
                (mem.index == reg && mem.base == X86_REG_INVALID && mem.scale == 1));
    }
    case X86_INS_JMP:
    case X86_INS_JA:
    case X86_INS_JAE:
    case X86_INS_JB:
    case X86_INS_JBE:
    case X86_INS_JE:
    case X86_INS_JNE:
    case X86_INS_JG:
    case X86_INS_JGE:
    case X86_INS_JL:
    case X86_INS_JLE:
    case X86_INS_JO:
    case X86_INS_JNO:
    case X86_INS_JP:
    case X86_INS_JNP:
    case X86_INS_JS:
    case X86_INS_JNS:
    case X86_INS_JECXZ:
    case X86_INS_JCXZ:
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        // jmp 0
        op = ops[0];
        return op.type == X86_OP_IMM && op.imm == 0;
    case X86_INS_SHL:
    case X86_INS_SHR:
    case X86_INS_ROL:
    case X86_INS_ROR:
    case X86_INS_SAR:
    case X86_INS_SAL:
    case X86_INS_SHLD:
    case X86_INS_SHRD:
        // shl eax, 0
        op = ops[OpCount() - 1];
        return op.type == X86_OP_IMM && op.imm == 0;
    default:
        return false;
    }
}

bool Capstone::IsInt3() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_INT3:
        return true;
    case X86_INS_INT:
    {
        cs_x86_op op = x86().operands[0];
        return op.type == X86_OP_IMM && op.imm == 3;
    }
    default:
        return false;
    }
}

bool Capstone::IsUnusual() const
{
    auto id = GetId();
    return (InGroup(CS_GRP_PRIVILEGE) || InGroup(CS_GRP_IRET) || InGroup(CS_GRP_INVALID)
            || id == X86_INS_RDTSC || id == X86_INS_SYSCALL || id == X86_INS_SYSENTER || id == X86_INS_CPUID || id == X86_INS_RDTSCP
            || id == X86_INS_RDRAND || id == X86_INS_RDSEED);
}

std::string Capstone::Mnemonic() const
{
    if(!Success())
        return "???";
    return mInstr->mnemonic;
}

std::string Capstone::MnemonicId() const
{
    if(!Success())
        return "???";
    return cs_insn_name(mHandle, GetId());
}

const char* Capstone::MemSizeName(int size) const
{
    switch(size)
    {
    case 1:
        return "byte";
    case 2:
        return "word";
    case 4:
        return "dword";
    case 6:
        return "fword";
    case 8:
        return "qword";
    case 10:
        return "tword";
    case 16:
        return "dqword";
    case 32:
        return "yword";
    case 64:
        return "zword";
    default:
        return nullptr;
    }
}

size_t Capstone::BranchDestination() const
{
    if(!Success())
        return 0;
    if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
    {
        const auto & op = x86().operands[0];
        if(op.type == CS_OP_IMM)
            return size_t(op.imm);
    }
    return 0;
}

size_t Capstone::ResolveOpValue(int opindex, const std::function<size_t(x86_reg)> & resolveReg) const
{
    size_t dest = 0;
    const auto & op = x86().operands[opindex];
    switch(op.type)
    {
    case X86_OP_IMM:
        dest = size_t(op.imm);
        break;
    case X86_OP_REG:
        dest = resolveReg(op.reg);
        break;
    case X86_OP_MEM:
        dest = size_t(op.mem.disp);
        if(op.mem.base == X86_REG_RIP) //rip-relative
            dest += Address() + Size();
        else
            dest += resolveReg(op.mem.base) + resolveReg(op.mem.index) * op.mem.scale;
        break;
    default:
        break;
    }
    return dest;
}
<|endoftext|>


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

#include <string>

#include "app/l10n_util.h"
#include "base/sys_info.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

const std::string BEFORE_UNLOAD_HTML =
    "<title>beforeunload</title>"
    ""
    "";

const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE =
    L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};";

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
  // On Mac or ChromeOS, we don't want to suffix the page title with
  // the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#elif defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#endif
}

// Returns the number of active RenderProcessHosts.
int CountRenderProcessHosts() {
  int result = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    ++result;
  return result;
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title1.html"));
  ui_test_utils::NavigateToURL(browser(), url);
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  TabContents* second_tab = browser()->GetTabContentsAt(1);
  ASSERT_TRUE(second_tab);
  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"",
      L"alert('Activate!');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
}
#endif  // !defined(OS_MACOSX)

// Create 34 tabs and verify that a lot of processes have been created. The
// exact number of processes depends on the amount of memory. Previously we
// had a hard limit of 31 processes and this test is mainly directed at
// verifying that we don't crash when we pass this limit.
IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title2.html"));

  // There is one initial tab.
  for (int ix = 0; ix != 33; ++ix) {
    browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                             true, 0, false, NULL);
  }
  EXPECT_EQ(34, browser()->tab_count());

  // See browser\renderer_host\render_process_host.cc for the algorithm to
  // decide how many processes to create.
  if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
    EXPECT_GE(CountRenderProcessHosts(), 24);
  } else {
    EXPECT_LE(CountRenderProcessHosts(), 23);
  }
}

// Test for crbug.com/22004.  Reloading a page with a before unload handler and
// then canceling the dialog should not leave the throbber spinning.
IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
  GURL url("data:text/html," + BEFORE_UNLOAD_HTML);
  ui_test_utils::NavigateToURL(browser(), url);

  // Navigate to another page, but click cancel in the dialog.  Make sure that
  // the throbber stops spinning.
  browser()->Reload();
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading());

  // Clear the beforeunload handler so the test can easily exit.
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;");
}

// Disable this test for Linux.
// TODO(port) BUG=crbug.com/27893
#if !defined(OS_LINUX)
// Test for crbug.com/11647.  A page closed with window.close() should not have
// two beforeunload dialogs shown.
IN_PROC_BROWSER_TEST_F(BrowserTest, FLAKY_SingleBeforeUnloadAfterWindowClose) {
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE);

  // Close the new window with JavaScript, which should show a single
  // beforeunload dialog.  Then show another alert, to make it easy to verify
  // that a second beforeunload dialog isn't shown.
  browser()->GetTabContentsAt(0)->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->AcceptWindow();

  alert = ui_test_utils::WaitForAppModalDialog();
  EXPECT_FALSE(alert->is_before_unload_dialog());
  alert->AcceptWindow();
}
#endif

// Test that get_process_idle_time() returns reasonable values when compared
// with time deltas measured locally.
IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
  base::TimeTicks start = base::TimeTicks::Now();
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
  for (; !it.IsAtEnd(); it.Advance()) {
    base::TimeDelta renderer_td =
        it.GetCurrentValue()->get_child_process_idle_time();
    base::TimeDelta browser_td = base::TimeTicks::Now() - start;
    EXPECT_TRUE(browser_td >= renderer_td);
  }
}
<commit_msg>Revert r32108 and re-enable BrowserTest.FLAKY_SingleBeforeUnloadAfterWindowClose on Linux.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "base/sys_info.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

const std::string BEFORE_UNLOAD_HTML =
    "<title>beforeunload</title>"
    ""
    "";

const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE =
    L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};";

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
  // On Mac or ChromeOS, we don't want to suffix the page title with
  // the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#elif defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#endif
}

// Returns the number of active RenderProcessHosts.
int CountRenderProcessHosts() {
  int result = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    ++result;
  return result;
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title1.html"));
  ui_test_utils::NavigateToURL(browser(), url);
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  TabContents* second_tab = browser()->GetTabContentsAt(1);
  ASSERT_TRUE(second_tab);
  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"",
      L"alert('Activate!');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
}
#endif  // !defined(OS_MACOSX)

// Create 34 tabs and verify that a lot of processes have been created. The
// exact number of processes depends on the amount of memory. Previously we
// had a hard limit of 31 processes and this test is mainly directed at
// verifying that we don't crash when we pass this limit.
IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title2.html"));

  // There is one initial tab.
  for (int ix = 0; ix != 33; ++ix) {
    browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                             true, 0, false, NULL);
  }
  EXPECT_EQ(34, browser()->tab_count());

  // See browser\renderer_host\render_process_host.cc for the algorithm to
  // decide how many processes to create.
  if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
    EXPECT_GE(CountRenderProcessHosts(), 24);
  } else {
    EXPECT_LE(CountRenderProcessHosts(), 23);
  }
}

// Test for crbug.com/22004.  Reloading a page with a before unload handler and
// then canceling the dialog should not leave the throbber spinning.
IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
  GURL url("data:text/html," + BEFORE_UNLOAD_HTML);
  ui_test_utils::NavigateToURL(browser(), url);

  // Navigate to another page, but click cancel in the dialog.  Make sure that
  // the throbber stops spinning.
  browser()->Reload();
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading());

  // Clear the beforeunload handler so the test can easily exit.
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;");
}

// Test for crbug.com/11647.  A page closed with window.close() should not have
// two beforeunload dialogs shown.
IN_PROC_BROWSER_TEST_F(BrowserTest, FLAKY_SingleBeforeUnloadAfterWindowClose) {
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE);

  // Close the new window with JavaScript, which should show a single
  // beforeunload dialog.  Then show another alert, to make it easy to verify
  // that a second beforeunload dialog isn't shown.
  browser()->GetTabContentsAt(0)->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->AcceptWindow();

  alert = ui_test_utils::WaitForAppModalDialog();
  EXPECT_FALSE(alert->is_before_unload_dialog());
  alert->AcceptWindow();
}

// Test that get_process_idle_time() returns reasonable values when compared
// with time deltas measured locally.
IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
  base::TimeTicks start = base::TimeTicks::Now();
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
  for (; !it.IsAtEnd(); it.Advance()) {
    base::TimeDelta renderer_td =
        it.GetCurrentValue()->get_child_process_idle_time();
    base::TimeDelta browser_td = base::TimeTicks::Now() - start;
    EXPECT_TRUE(browser_td >= renderer_td);
  }
}
<|endoftext|>


<commit_before>#include <StdAfx.h>
#include <UI/Controls/PaneHeader/PaneHeader.h>
#include <UI/UIFunctions.h>
#include <core/utility/strings.h>
#include <UI/DoubleBuffer.h>
#include <core/utility/output.h>
#include <core/utility/registry.h>

namespace controls
{
	static std::wstring CLASS = L"PaneHeader";

	PaneHeader::~PaneHeader()
	{
		TRACE_DESTRUCTOR(CLASS);
		CWnd::DestroyWindow();
	}

	void PaneHeader::Initialize(HWND hWnd, _In_opt_ HDC hdc, _In_ UINT nid)
	{
		m_hWndParent = hWnd;

		// Assign a nID to the collapse button that is IDD_COLLAPSE more than the control's nID
		m_nID = nid;
		m_nIDCollapse = nid + IDD_COLLAPSE;

		WNDCLASSEX wc = {};
		const auto hInst = AfxGetInstanceHandle();
		if (!::GetClassInfoEx(hInst, _T("PaneHeader"), &wc)) // STRING_OK
		{
			wc.cbSize = sizeof wc;
			wc.style = 0; // not passing CS_VREDRAW | CS_HREDRAW fixes flicker
			wc.lpszClassName = _T("PaneHeader"); // STRING_OK
			wc.lpfnWndProc = ::DefWindowProc;
			wc.hbrBackground = GetSysBrush(ui::uiColor::Background); // helps spot flashing

			RegisterClassEx(&wc);
		}

		// WS_CLIPCHILDREN is used to reduce flicker
		EC_B_S(CreateEx(
			0,
			_T("PaneHeader"), // STRING_OK
			_T("PaneHeader"), // STRING_OK
			WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE,
			0,
			0,
			0,
			0,
			m_hWndParent,
			reinterpret_cast<HMENU>(static_cast<INT_PTR>(IDC_PANE_HEADER)),
			nullptr));

		// We hang if we do this:
		// Necessary for TAB to work. Without this, all TABS get stuck on the control
		// instead of passing to the children.
		//EC_B_S(ModifyStyleEx(0, WS_EX_CONTROLPARENT));

		const auto sizeText = ui::GetTextExtentPoint32(hdc, m_szLabel);
		m_iLabelWidth = sizeText.cx;
		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::Initialize m_iLabelWidth:%d \"%ws\"\n",
			m_iLabelWidth,
			m_szLabel.c_str());
	}

	BEGIN_MESSAGE_MAP(PaneHeader, CWnd)
	ON_WM_CREATE()
	ON_WM_WINDOWPOSCHANGED()
	END_MESSAGE_MAP()

	int PaneHeader::OnCreate(LPCREATESTRUCT /*lpCreateStruct*/)
	{
		EC_B_S(m_leftLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE | WS_TABSTOP, CRect(0, 0, 0, 0), this, m_nID));
		::SetWindowTextW(m_leftLabel.m_hWnd, m_szLabel.c_str());
		ui::SubclassLabel(m_leftLabel.m_hWnd);
		if (m_bCollapsible)
		{
			StyleLabel(m_leftLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderLabel);
		}

		EC_B_S(m_rightLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE | WS_TABSTOP,
			CRect(0, 0, 0, 0),
			this,
			IDD_COUNTLABEL));
		ui::SubclassLabel(m_rightLabel.m_hWnd);
		StyleLabel(m_rightLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderText);

		if (m_bCollapsible)
		{
			EC_B_S(m_CollapseButton.Create(
				nullptr, WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, CRect(0, 0, 0, 0), this, m_nIDCollapse));
			StyleButton(
				m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		}

		// If we need an action button, go ahead and create it
		if (m_nIDAction)
		{
			EC_B_S(m_actionButton.Create(
				strings::wstringTotstring(m_szActionButton).c_str(),
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				this,
				m_nIDAction));
			StyleButton(m_actionButton.m_hWnd, ui::uiButtonStyle::Unstyled);
		}

		m_bInitialized = true;
		return 0;
	}

	LRESULT PaneHeader::WindowProc(const UINT message, const WPARAM wParam, const LPARAM lParam)
	{
		LRESULT lRes = 0;
		if (ui::HandleControlUI(message, wParam, lParam, &lRes)) return lRes;

		switch (message)
		{
		case WM_PAINT:
			auto ps = PAINTSTRUCT{};
			::BeginPaint(m_hWnd, &ps);
			if (ps.hdc)
			{
				auto rcWin = RECT{};
				::GetClientRect(m_hWnd, &rcWin);
				const auto background = registry::uiDiag ? ui::GetSysBrush(ui::uiColor::TestGreen)
														 : ui::GetSysBrush(ui::uiColor::Background);
				FillRect(ps.hdc, &rcWin, background);
			}

			::EndPaint(m_hWnd, &ps);
			return 0;
			break;
		case WM_CLOSE:
			::SendMessage(m_hWndParent, message, wParam, lParam);
			return true;
		case WM_HELP:
			return true;
		case WM_COMMAND:
		{
			const auto nCode = HIWORD(wParam);
			if (EN_CHANGE == nCode || CBN_SELCHANGE == nCode || CBN_EDITCHANGE == nCode || BN_CLICKED == nCode)
			{
				::SendMessage(m_hWndParent, message, wParam, lParam);
			}

			break;
		}
		}

		return CWnd::WindowProc(message, wParam, lParam);
	}

	// Draw our collapse button and label, if needed.
	// Draws everything to GetFixedHeight()
	void PaneHeader::OnWindowPosChanged(WINDOWPOS* lpwndpos)
	{
		if (!m_bInitialized || !lpwndpos) return; // TODO: wrap
		auto hWinPosInfo = WC_D(HDWP, BeginDeferWindowPos(2));
		if (hWinPosInfo)
		{
			const auto width = lpwndpos->cx;
			const auto height = lpwndpos->cy;
			output::DebugPrint(
				output::dbgLevel::Draw,
				L"PaneHeader::DeferWindowPos width:%d height:%d v:%d\n",
				width,
				height,
				IsWindowVisible());
			auto curX = 0;
			const auto actionButtonWidth = m_actionButtonWidth ? m_actionButtonWidth + 2 * m_iMargin : 0;
			const auto actionButtonAndGutterWidth = actionButtonWidth ? actionButtonWidth + m_iSideMargin : 0;
			if (m_bCollapsible)
			{
				hWinPosInfo = ui::DeferWindowPos(
					hWinPosInfo,
					m_CollapseButton.GetSafeHwnd(),
					curX,
					0,
					width - actionButtonAndGutterWidth,
					height,
					L"PaneHeader::DeferWindowPos::collapseButton");
				curX += m_iButtonHeight;
			}

			hWinPosInfo = ui::DeferWindowPos(
				hWinPosInfo,
				m_leftLabel.GetSafeHwnd(),
				curX,
				0,
				m_iLabelWidth,
				height,
				L"PaneHeader::DeferWindowPos::leftLabel");

			if (!m_bCollapsed)
			{
				// Drop the count on top of the label we drew above
				if (m_rightLabel.GetSafeHwnd())
				{
					hWinPosInfo = ui::DeferWindowPos(
						hWinPosInfo,
						m_rightLabel.GetSafeHwnd(),
						width - m_rightLabelWidth - actionButtonAndGutterWidth,
						0,
						m_rightLabelWidth,
						height,
						L"PaneHeader::DeferWindowPos::rightLabel");
				}
			}

			if (m_nIDAction)
			{
				// Drop the action button next to the label we drew above
				hWinPosInfo = ui::DeferWindowPos(
					hWinPosInfo,
					m_actionButton.GetSafeHwnd(),
					width - actionButtonWidth,
					0,
					actionButtonWidth,
					height,
					L"PaneHeader::DeferWindowPos::actionButton");
			}

			output::DebugPrint(output::dbgLevel::Draw, L"PaneHeader::DeferWindowPos end\n");
			EC_B_S(EndDeferWindowPos(hWinPosInfo));
		}

		return CWnd::OnWindowPosChanged(lpwndpos);
	}

	void PaneHeader::Redraw()
	{
		// Trigger a redraw
		RECT rcControl = {0};
		::GetWindowRect(GetSafeHwnd(), &rcControl);
		::MoveWindow(
			GetSafeHwnd(),
			rcControl.left,
			rcControl.top,
			rcControl.right - rcControl.left,
			rcControl.bottom - rcControl.top,
			false);
	}

	int PaneHeader::GetMinWidth()
	{
		auto cx = m_iLabelWidth;
		if (m_bCollapsible) cx += m_iButtonHeight;
		if (m_rightLabelWidth)
		{
			cx += m_iSideMargin;
			cx += m_rightLabelWidth;
		}

		if (m_actionButtonWidth)
		{
			cx += m_iSideMargin;
			cx += m_actionButtonWidth + 2 * m_iMargin;
		}

		return cx;
	}

	void PaneHeader::SetRightLabel(const std::wstring szLabel)
	{
		if (!m_bInitialized) return;
		EC_B_S(::SetWindowTextW(m_rightLabel.m_hWnd, szLabel.c_str()));

		const auto hdc = ::GetDC(m_rightLabel.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szLabel);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_rightLabel.GetSafeHwnd(), hdc);
		m_rightLabelWidth = sizeText.cx;

		Redraw();
	}

	void PaneHeader::SetActionButton(const std::wstring szActionButton)
	{
		// Don't bother if we never enabled the button
		if (m_nIDAction == 0) return;

		EC_B_S(::SetWindowTextW(m_actionButton.GetSafeHwnd(), szActionButton.c_str()));

		m_szActionButton = szActionButton;
		const auto hdc = ::GetDC(m_actionButton.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szActionButton);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_actionButton.GetSafeHwnd(), hdc);
		m_actionButtonWidth = sizeText.cx;

		Redraw();
	}

	bool PaneHeader::HandleChange(UINT nID)
	{
		// Collapse buttons have a nID IDD_COLLAPSE higher than nID of the pane they toggle.
		// So if we get asked about one that matches, we can assume it's time to toggle our collapse.
		if (m_nIDCollapse == nID)
		{
			OnToggleCollapse();
			return true;
		}

		return false;
	}

	void PaneHeader::OnToggleCollapse()
	{
		m_bCollapsed = !m_bCollapsed;

		StyleButton(m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		WC_B_S(m_rightLabel.ShowWindow(m_bCollapsed ? SW_HIDE : SW_SHOW));

		// Trigger a redraw
		::PostMessage(m_hWndParent, WM_COMMAND, IDD_RECALCLAYOUT, NULL);
	}

	void PaneHeader::SetMargins(
		int iMargin,
		int iSideMargin,
		int iLabelHeight, // Height of the label
		int iButtonHeight) // Height of button
	{
		m_iMargin = iMargin;
		m_iSideMargin = iSideMargin;
		m_iLabelHeight = iLabelHeight;
		m_iButtonHeight = iButtonHeight;
	}
} // namespace controls<commit_msg>remove some dead code<commit_after>#include <StdAfx.h>
#include <UI/Controls/PaneHeader/PaneHeader.h>
#include <UI/UIFunctions.h>
#include <core/utility/strings.h>
#include <UI/DoubleBuffer.h>
#include <core/utility/output.h>
#include <core/utility/registry.h>

namespace controls
{
	static std::wstring CLASS = L"PaneHeader";

	PaneHeader::~PaneHeader()
	{
		TRACE_DESTRUCTOR(CLASS);
		CWnd::DestroyWindow();
	}

	void PaneHeader::Initialize(HWND hWnd, _In_opt_ HDC hdc, _In_ UINT nid)
	{
		m_hWndParent = hWnd;

		// Assign a nID to the collapse button that is IDD_COLLAPSE more than the control's nID
		m_nID = nid;
		m_nIDCollapse = nid + IDD_COLLAPSE;

		WNDCLASSEX wc = {};
		const auto hInst = AfxGetInstanceHandle();
		if (!::GetClassInfoEx(hInst, _T("PaneHeader"), &wc)) // STRING_OK
		{
			wc.cbSize = sizeof wc;
			wc.style = 0; // not passing CS_VREDRAW | CS_HREDRAW fixes flicker
			wc.lpszClassName = _T("PaneHeader"); // STRING_OK
			wc.lpfnWndProc = ::DefWindowProc;
			wc.hbrBackground = GetSysBrush(ui::uiColor::Background); // helps spot flashing

			RegisterClassEx(&wc);
		}

		// WS_CLIPCHILDREN is used to reduce flicker
		EC_B_S(CreateEx(
			0,
			_T("PaneHeader"), // STRING_OK
			_T("PaneHeader"), // STRING_OK
			WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE,
			0,
			0,
			0,
			0,
			m_hWndParent,
			reinterpret_cast<HMENU>(static_cast<INT_PTR>(IDC_PANE_HEADER)),
			nullptr));

		// We hang if we do this:
		// Necessary for TAB to work. Without this, all TABS get stuck on the control
		// instead of passing to the children.
		//EC_B_S(ModifyStyleEx(0, WS_EX_CONTROLPARENT));

		const auto sizeText = ui::GetTextExtentPoint32(hdc, m_szLabel);
		m_iLabelWidth = sizeText.cx;
		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::Initialize m_iLabelWidth:%d \"%ws\"\n",
			m_iLabelWidth,
			m_szLabel.c_str());
	}

	BEGIN_MESSAGE_MAP(PaneHeader, CWnd)
	ON_WM_CREATE()
	ON_WM_WINDOWPOSCHANGED()
	END_MESSAGE_MAP()

	int PaneHeader::OnCreate(LPCREATESTRUCT /*lpCreateStruct*/)
	{
		EC_B_S(m_leftLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE | WS_TABSTOP, CRect(0, 0, 0, 0), this, m_nID));
		::SetWindowTextW(m_leftLabel.m_hWnd, m_szLabel.c_str());
		ui::SubclassLabel(m_leftLabel.m_hWnd);
		if (m_bCollapsible)
		{
			StyleLabel(m_leftLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderLabel);
		}

		EC_B_S(m_rightLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE | WS_TABSTOP,
			CRect(0, 0, 0, 0),
			this,
			IDD_COUNTLABEL));
		ui::SubclassLabel(m_rightLabel.m_hWnd);
		StyleLabel(m_rightLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderText);

		if (m_bCollapsible)
		{
			EC_B_S(m_CollapseButton.Create(
				nullptr, WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, CRect(0, 0, 0, 0), this, m_nIDCollapse));
			StyleButton(
				m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		}

		// If we need an action button, go ahead and create it
		if (m_nIDAction)
		{
			EC_B_S(m_actionButton.Create(
				strings::wstringTotstring(m_szActionButton).c_str(),
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				this,
				m_nIDAction));
			StyleButton(m_actionButton.m_hWnd, ui::uiButtonStyle::Unstyled);
		}

		m_bInitialized = true;
		return 0;
	}

	LRESULT PaneHeader::WindowProc(const UINT message, const WPARAM wParam, const LPARAM lParam)
	{
		LRESULT lRes = 0;
		if (ui::HandleControlUI(message, wParam, lParam, &lRes)) return lRes;

		switch (message)
		{
		case WM_PAINT:
			auto ps = PAINTSTRUCT{};
			::BeginPaint(m_hWnd, &ps);
			if (ps.hdc)
			{
				auto rcWin = RECT{};
				::GetClientRect(m_hWnd, &rcWin);
				const auto background = registry::uiDiag ? ui::GetSysBrush(ui::uiColor::TestGreen)
														 : ui::GetSysBrush(ui::uiColor::Background);
				FillRect(ps.hdc, &rcWin, background);
			}

			::EndPaint(m_hWnd, &ps);
			return 0;
			break;
		case WM_CLOSE:
			::SendMessage(m_hWndParent, message, wParam, lParam);
			return true;
		case WM_HELP:
			return true;
		case WM_COMMAND:
		{
			const auto nCode = HIWORD(wParam);
			// Pass button clicks up to parent
			if (BN_CLICKED == nCode)
			{
				::SendMessage(m_hWndParent, message, wParam, lParam);
			}

			break;
		}
		}

		return CWnd::WindowProc(message, wParam, lParam);
	}

	// Draw our collapse button and label, if needed.
	// Draws everything to GetFixedHeight()
	void PaneHeader::OnWindowPosChanged(WINDOWPOS* lpwndpos)
	{
		if (!m_bInitialized || !lpwndpos) return; // TODO: wrap
		auto hWinPosInfo = WC_D(HDWP, BeginDeferWindowPos(2));
		if (hWinPosInfo)
		{
			const auto width = lpwndpos->cx;
			const auto height = lpwndpos->cy;
			output::DebugPrint(
				output::dbgLevel::Draw,
				L"PaneHeader::DeferWindowPos width:%d height:%d v:%d\n",
				width,
				height,
				IsWindowVisible());
			auto curX = 0;
			const auto actionButtonWidth = m_actionButtonWidth ? m_actionButtonWidth + 2 * m_iMargin : 0;
			const auto actionButtonAndGutterWidth = actionButtonWidth ? actionButtonWidth + m_iSideMargin : 0;
			if (m_bCollapsible)
			{
				hWinPosInfo = ui::DeferWindowPos(
					hWinPosInfo,
					m_CollapseButton.GetSafeHwnd(),
					curX,
					0,
					width - actionButtonAndGutterWidth,
					height,
					L"PaneHeader::DeferWindowPos::collapseButton");
				curX += m_iButtonHeight;
			}

			hWinPosInfo = ui::DeferWindowPos(
				hWinPosInfo,
				m_leftLabel.GetSafeHwnd(),
				curX,
				0,
				m_iLabelWidth,
				height,
				L"PaneHeader::DeferWindowPos::leftLabel");

			if (!m_bCollapsed)
			{
				// Drop the count on top of the label we drew above
				if (m_rightLabel.GetSafeHwnd())
				{
					hWinPosInfo = ui::DeferWindowPos(
						hWinPosInfo,
						m_rightLabel.GetSafeHwnd(),
						width - m_rightLabelWidth - actionButtonAndGutterWidth,
						0,
						m_rightLabelWidth,
						height,
						L"PaneHeader::DeferWindowPos::rightLabel");
				}
			}

			if (m_nIDAction)
			{
				// Drop the action button next to the label we drew above
				hWinPosInfo = ui::DeferWindowPos(
					hWinPosInfo,
					m_actionButton.GetSafeHwnd(),
					width - actionButtonWidth,
					0,
					actionButtonWidth,
					height,
					L"PaneHeader::DeferWindowPos::actionButton");
			}

			output::DebugPrint(output::dbgLevel::Draw, L"PaneHeader::DeferWindowPos end\n");
			EC_B_S(EndDeferWindowPos(hWinPosInfo));
		}

		return CWnd::OnWindowPosChanged(lpwndpos);
	}

	void PaneHeader::Redraw()
	{
		// Trigger a redraw
		RECT rcControl = {0};
		::GetWindowRect(GetSafeHwnd(), &rcControl);
		::MoveWindow(
			GetSafeHwnd(),
			rcControl.left,
			rcControl.top,
			rcControl.right - rcControl.left,
			rcControl.bottom - rcControl.top,
			false);
	}

	int PaneHeader::GetMinWidth()
	{
		auto cx = m_iLabelWidth;
		if (m_bCollapsible) cx += m_iButtonHeight;
		if (m_rightLabelWidth)
		{
			cx += m_iSideMargin;
			cx += m_rightLabelWidth;
		}

		if (m_actionButtonWidth)
		{
			cx += m_iSideMargin;
			cx += m_actionButtonWidth + 2 * m_iMargin;
		}

		return cx;
	}

	void PaneHeader::SetRightLabel(const std::wstring szLabel)
	{
		if (!m_bInitialized) return;
		EC_B_S(::SetWindowTextW(m_rightLabel.m_hWnd, szLabel.c_str()));

		const auto hdc = ::GetDC(m_rightLabel.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szLabel);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_rightLabel.GetSafeHwnd(), hdc);
		m_rightLabelWidth = sizeText.cx;

		Redraw();
	}

	void PaneHeader::SetActionButton(const std::wstring szActionButton)
	{
		// Don't bother if we never enabled the button
		if (m_nIDAction == 0) return;

		EC_B_S(::SetWindowTextW(m_actionButton.GetSafeHwnd(), szActionButton.c_str()));

		m_szActionButton = szActionButton;
		const auto hdc = ::GetDC(m_actionButton.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szActionButton);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_actionButton.GetSafeHwnd(), hdc);
		m_actionButtonWidth = sizeText.cx;

		Redraw();
	}

	bool PaneHeader::HandleChange(UINT nID)
	{
		// Collapse buttons have a nID IDD_COLLAPSE higher than nID of the pane they toggle.
		// So if we get asked about one that matches, we can assume it's time to toggle our collapse.
		if (m_nIDCollapse == nID)
		{
			OnToggleCollapse();
			return true;
		}

		return false;
	}

	void PaneHeader::OnToggleCollapse()
	{
		m_bCollapsed = !m_bCollapsed;

		StyleButton(m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		WC_B_S(m_rightLabel.ShowWindow(m_bCollapsed ? SW_HIDE : SW_SHOW));

		// Trigger a redraw
		::PostMessage(m_hWndParent, WM_COMMAND, IDD_RECALCLAYOUT, NULL);
	}

	void PaneHeader::SetMargins(
		int iMargin,
		int iSideMargin,
		int iLabelHeight, // Height of the label
		int iButtonHeight) // Height of button
	{
		m_iMargin = iMargin;
		m_iSideMargin = iSideMargin;
		m_iLabelHeight = iLabelHeight;
		m_iButtonHeight = iButtonHeight;
	}
} // namespace controls<|endoftext|>


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

#include "chrome/browser/gpu/chrome_gpu_util.h"

#include "base/command_line.h"
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#endif
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/version.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"

using content::GpuDataManager;

namespace gpu_util {

void DisableCompositingFieldTrial() {
  base::FieldTrial* trial =
      base::FieldTrialList::Find(content::kGpuCompositingFieldTrialName);
  if (trial)
    trial->Disable();
}

bool ShouldRunCompositingFieldTrial() {
// Enable the field trial only on desktop OS's.
#if !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
  return false;
#endif

// Necessary for linux_chromeos build since it defines both OS_LINUX
// and OS_CHROMEOS.
#if defined(OS_CHROMEOS)
  return false;
#endif

#if defined(OS_WIN)
  // Don't run the trial on Windows XP.
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return false;
#endif

#if defined(OS_MACOSX)
  // Browser and content shell tests hang on 10.7 when the Apple software
  // renderer is used. These tests ignore the blacklist (which disables
  // compositing both on 10.7 and when the Apple software renderer is used)
  // by specifying the kSkipGpuDataLoading switch, so disable forced
  // compositing here based on the switch and OS version.
  // http://crbug.com/230931
  if (base::mac::IsOSLion() &&
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kSkipGpuDataLoading)) {
    return false;
  }
#endif

  // Don't activate the field trial if force-compositing-mode has been
  // explicitly disabled from the command line.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableForceCompositingMode) ||
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableAcceleratedCompositing))
    return false;

  return true;
}

// Note 1: The compositing field trial may be created at startup time via the
// Finch framework. In that case, all the Groups and probability values are
// set before this function is called and any Field Trial setup calls
// made here are simply ignored.
// Note 2: Compositing field trials will be overwritten if accelerated
// compositing is blacklisted. That check takes place in
// IsThreadedCompositingEnabled() and IsForceCompositingModeEnabled() as
// the blacklist information isn't available at the time the field trials
// are initialized.
// Early outs from this function intended to bypass activation of the field
// trial must call DisableCompositingFieldTrial() before returning.
void InitializeCompositingFieldTrial() {
  // Early out in configurations that should not run the compositing
  // field trial.
  if (!ShouldRunCompositingFieldTrial()) {
    DisableCompositingFieldTrial();
    return;
  }

  const base::FieldTrial::Probability kDivisor = 3;
  scoped_refptr<base::FieldTrial> trial(
    base::FieldTrialList::FactoryGetFieldTrial(
        content::kGpuCompositingFieldTrialName, kDivisor,
        "disable", 2013, 12, 31, NULL));

  // Produce the same result on every run of this client.
  trial->UseOneTimeRandomization();

  base::FieldTrial::Probability force_compositing_mode_probability = 0;
  base::FieldTrial::Probability threaded_compositing_probability = 0;

  // Note: Threaded compositing mode isn't feature complete on mac or linux yet:
  // http://crbug.com/133602 for mac
  // http://crbug.com/140866 for linux

#if defined(OS_WIN)
  // Enable threaded compositing on Windows.
  threaded_compositing_probability = kDivisor;
#elif defined(OS_MACOSX)
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_CANARY ||
      channel == chrome::VersionInfo::CHANNEL_DEV) {
    // Enable force-compositing-mode on the Mac.
    force_compositing_mode_probability = kDivisor;
  }
#endif

  int force_compositing_group = trial->AppendGroup(
      content::kGpuCompositingFieldTrialForceCompositingEnabledName,
      force_compositing_mode_probability);
  int thread_group = trial->AppendGroup(
      content::kGpuCompositingFieldTrialThreadEnabledName,
      threaded_compositing_probability);

  bool force_compositing = (trial->group() == force_compositing_group);
  bool thread = (trial->group() == thread_group);
  UMA_HISTOGRAM_BOOLEAN("GPU.InForceCompositingModeFieldTrial",
                        force_compositing);
  UMA_HISTOGRAM_BOOLEAN("GPU.InCompositorThreadFieldTrial", thread);
}

}  // namespace gpu_util;

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

#include "chrome/browser/gpu/chrome_gpu_util.h"

#include "base/command_line.h"
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#endif
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/version.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"

using content::GpuDataManager;

namespace gpu_util {

void DisableCompositingFieldTrial() {
  base::FieldTrial* trial =
      base::FieldTrialList::Find(content::kGpuCompositingFieldTrialName);
  if (trial)
    trial->Disable();
}

bool ShouldRunCompositingFieldTrial() {
// Enable the field trial only on desktop OS's.
#if !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
  return false;
#endif

// Necessary for linux_chromeos build since it defines both OS_LINUX
// and OS_CHROMEOS.
#if defined(OS_CHROMEOS)
  return false;
#endif

#if defined(OS_WIN)
  // Don't run the trial on Windows XP.
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return false;
#endif

#if defined(OS_MACOSX)
  // Browser and content shell tests hang on 10.7 when the Apple software
  // renderer is used. These tests ignore the blacklist (which disables
  // compositing both on 10.7 and when the Apple software renderer is used)
  // by specifying the kSkipGpuDataLoading switch, so disable forced
  // compositing here based on the switch and OS version.
  // http://crbug.com/230931
  if (base::mac::IsOSLion() &&
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kSkipGpuDataLoading)) {
    return false;
  }
#endif

  // Don't activate the field trial if force-compositing-mode has been
  // explicitly disabled from the command line.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableForceCompositingMode) ||
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableAcceleratedCompositing))
    return false;

  return true;
}

// Note 1: The compositing field trial may be created at startup time via the
// Finch framework. In that case, all the Groups and probability values are
// set before this function is called and any Field Trial setup calls
// made here are simply ignored.
// Note 2: Compositing field trials will be overwritten if accelerated
// compositing is blacklisted. That check takes place in
// IsThreadedCompositingEnabled() and IsForceCompositingModeEnabled() as
// the blacklist information isn't available at the time the field trials
// are initialized.
// Early outs from this function intended to bypass activation of the field
// trial must call DisableCompositingFieldTrial() before returning.
void InitializeCompositingFieldTrial() {
  // Early out in configurations that should not run the compositing
  // field trial.
  if (!ShouldRunCompositingFieldTrial()) {
    DisableCompositingFieldTrial();
    return;
  }

  const base::FieldTrial::Probability kDivisor = 3;
  scoped_refptr<base::FieldTrial> trial(
    base::FieldTrialList::FactoryGetFieldTrial(
        content::kGpuCompositingFieldTrialName, kDivisor,
        "disable", 2013, 12, 31, NULL));

  // Produce the same result on every run of this client.
  trial->UseOneTimeRandomization();

  base::FieldTrial::Probability force_compositing_mode_probability = 0;
  base::FieldTrial::Probability threaded_compositing_probability = 0;

  // Note: Threaded compositing mode isn't feature complete on mac or linux yet:
  // http://crbug.com/133602 for mac
  // http://crbug.com/140866 for linux

#if defined(OS_WIN) || defined(OS_MACOSX)
  // Enable threaded compositing on Windows and Mac.
  threaded_compositing_probability = kDivisor;
#endif

  int force_compositing_group = trial->AppendGroup(
      content::kGpuCompositingFieldTrialForceCompositingEnabledName,
      force_compositing_mode_probability);
  int thread_group = trial->AppendGroup(
      content::kGpuCompositingFieldTrialThreadEnabledName,
      threaded_compositing_probability);

  bool force_compositing = (trial->group() == force_compositing_group);
  bool thread = (trial->group() == thread_group);
  UMA_HISTOGRAM_BOOLEAN("GPU.InForceCompositingModeFieldTrial",
                        force_compositing);
  UMA_HISTOGRAM_BOOLEAN("GPU.InCompositorThreadFieldTrial", thread);
}

}  // namespace gpu_util;

<|endoftext|>