<commit_before>/***************************************************************************
 * Copyright 1998-2015 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include <cstddef>

#include "slg/cameras/orthographic.h"
#include "slg/cameras/perspective.h"
#include "slg/cameras/stereo.h"
#include "slg/film/film.h"
#include "slg/core/sdl.h"
#include "slg/scene/scene.h"

using namespace std;
using namespace luxrays;
using namespace slg;

//------------------------------------------------------------------------------
// Camera
//------------------------------------------------------------------------------

Properties Camera::ToProperties() const {
	Properties props;

	props.Set(Property("scene.camera.cliphither")(clipHither));
	props.Set(Property("scene.camera.clipyon")(clipYon));
	props.Set(Property("scene.camera.shutteropen")(shutterOpen));
	props.Set(Property("scene.camera.shutterclose")(shutterClose));

	if (motionSystem)
		props.Set(motionSystem->ToProperties("scene.camera."));

	return props;
}

//------------------------------------------------------------------------------
// Allocate a Camera
//------------------------------------------------------------------------------

Camera *Camera::AllocCamera(const luxrays::Properties &props) {
	Point orig, target;
	Vector up;
	if (props.IsDefined("scene.camera.lookat")) {
		SDL_LOG("WARNING: deprecated property scene.camera.lookat");

		const Property &prop = props.Get("scene.camera.lookat");
		orig.x = prop.Get<float>(0);
		orig.y = prop.Get<float>(1);
		orig.z = prop.Get<float>(2);
		target.x = prop.Get<float>(3);
		target.y = prop.Get<float>(4);
		target.z = prop.Get<float>(5);
		up = Vector(0.f, 0.f, 1.f);
	} else {
		if (!props.IsDefined("scene.camera.lookat.orig")) {
			// This is a trick I use from LuxCoreRenderer to set cameraToWorld to
			// identity matrix.
			//
			// I leave orig, target and up all set to (0.f, 0.f, 0.f)
		} else {
			orig = props.Get(Property("scene.camera.lookat.orig")(0.f, 10.f, 0.f)).Get<Point>();
			target = props.Get(Property("scene.camera.lookat.target")(0.f, 0.f, 0.f)).Get<Point>();
			up = props.Get(Property("scene.camera.up")(0.f, 0.f, 1.f)).Get<Vector>();
		}
	}

	const std::string type = props.Get(Property("scene.camera.type")("perspective")).Get<std::string>();

	SDL_LOG("Camera type: " << type);
	SDL_LOG("Camera position: " << orig);
	SDL_LOG("Camera target: " << target);

	auto_ptr<Camera> camera;
	if ((type == "orthographic") || (type == "perspective") || (type == "stereo")) {
		if (type == "orthographic") {
			OrthographicCamera *orthoCamera;

			if (props.IsDefined("scene.camera.screenwindow")) {
				float screenWindow[4];

				const Property &prop = props.Get(Property("scene.camera.screenwindow")(0.f, 1.f, 0.f, 1.f));
				screenWindow[0] = prop.Get<float>(0);
				screenWindow[1] = prop.Get<float>(1);
				screenWindow[2] = prop.Get<float>(2);
				screenWindow[3] = prop.Get<float>(3);

				orthoCamera = new OrthographicCamera(orig, target, up, &screenWindow[0]);
			} else
				orthoCamera = new OrthographicCamera(orig, target, up);

			camera.reset(orthoCamera);
		} else if (type == "perspective") {
			PerspectiveCamera *perspCamera;

			if (props.IsDefined("scene.camera.screenwindow")) {
				float screenWindow[4];

				const Property &prop = props.Get(Property("scene.camera.screenwindow")(0.f, 1.f, 0.f, 1.f));
				screenWindow[0] = prop.Get<float>(0);
				screenWindow[1] = prop.Get<float>(1);
				screenWindow[2] = prop.Get<float>(2);
				screenWindow[3] = prop.Get<float>(3);

				perspCamera = new PerspectiveCamera(orig, target, up, &screenWindow[0]);
			} else
				perspCamera = new PerspectiveCamera(orig, target, up);
			camera.reset(perspCamera);

			perspCamera->enableOculusRiftBarrel = props.Get(Property("scene.camera.oculusrift.barrelpostpro.enable")(false)).Get<bool>();
		} else {
			StereoCamera *stereoCamera = new StereoCamera(orig, target, up);
			camera.reset(stereoCamera);

			stereoCamera->enableOculusRiftBarrel = props.Get(Property("scene.camera.oculusrift.barrelpostpro.enable")(false)).Get<bool>();
			stereoCamera->horizStereoEyesDistance = props.Get(Property("scene.camera.eyesdistance")(.0626f)).Get<float>();
			stereoCamera->horizStereoLensDistance = props.Get(Property("scene.camera.lensdistance")(.2779f)).Get<float>();
		}

		ProjectiveCamera *projCamera = (ProjectiveCamera *)camera.get();

		projCamera->lensRadius = props.Get(Property("scene.camera.lensradius")(0.f)).Get<float>();
		projCamera->focalDistance = props.Get(Property("scene.camera.focaldistance")(10.f)).Get<float>();
		projCamera->autoFocus = props.Get(Property("scene.camera.autofocus.enable")(false)).Get<bool>();

		// Check if I have to arbitrary clipping plane
		if (props.Get(Property("scene.camera.clippingplane.enable")(false)).Get<bool>()) {
			projCamera->clippingPlaneCenter = props.Get(Property("scene.camera.clippingplane.center")(Point())).Get<Point>();
			projCamera->clippingPlaneNormal = props.Get(Property("scene.camera.clippingplane.normal")(Normal())).Get<Normal>();
			projCamera->enableClippingPlane = true;
			SDL_LOG("Camera clipping plane enabled");
		} else {
			projCamera->enableClippingPlane = false;
			SDL_LOG("Camera clipping plane disabled");
		}
	} else
		throw runtime_error("Unknown camera type: " + type);

	camera->clipHither = props.Get(Property("scene.camera.cliphither")(1e-3f)).Get<float>();
	camera->clipYon = props.Get(Property("scene.camera.clipyon")(1e30f)).Get<float>();
	camera->shutterOpen = props.Get(Property("scene.camera.shutteropen")(0.f)).Get<float>();
	camera->shutterClose = props.Get(Property("scene.camera.shutterclose")(1.f)).Get<float>();

	// Check if I have to use a motion system
	if (props.IsDefined("scene.camera.motion.0.time")) {
		// Build the motion system
		vector<float> times;
		vector<Transform> transforms;
		for (u_int i =0;; ++i) {
			const string prefix = "scene.camera.motion." + ToString(i);
			if (!props.IsDefined(prefix +".time"))
				break;

			const float t = props.Get(prefix +".time").Get<float>();
			if (i > 0 && t <= times.back())
				throw runtime_error("Motion camera time must be monotonic");
			times.push_back(t);

			const Matrix4x4 mat = props.Get(Property(prefix +
				".transformation")(Matrix4x4::MAT_IDENTITY)).Get<Matrix4x4>();
			transforms.push_back(Transform(mat));
		}

		camera->motionSystem = new MotionSystem(times, transforms);
	}

	return camera.release();
}
<commit_msg>Fixed fieldofview reading for perspective camera<commit_after>/***************************************************************************
 * Copyright 1998-2015 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include <cstddef>

#include "slg/cameras/orthographic.h"
#include "slg/cameras/perspective.h"
#include "slg/cameras/stereo.h"
#include "slg/film/film.h"
#include "slg/core/sdl.h"
#include "slg/scene/scene.h"

using namespace std;
using namespace luxrays;
using namespace slg;

//------------------------------------------------------------------------------
// Camera
//------------------------------------------------------------------------------

Properties Camera::ToProperties() const {
	Properties props;

	props.Set(Property("scene.camera.cliphither")(clipHither));
	props.Set(Property("scene.camera.clipyon")(clipYon));
	props.Set(Property("scene.camera.shutteropen")(shutterOpen));
	props.Set(Property("scene.camera.shutterclose")(shutterClose));

	if (motionSystem)
		props.Set(motionSystem->ToProperties("scene.camera."));

	return props;
}

//------------------------------------------------------------------------------
// Allocate a Camera
//------------------------------------------------------------------------------

Camera *Camera::AllocCamera(const luxrays::Properties &props) {
	Point orig, target;
	Vector up;
	if (props.IsDefined("scene.camera.lookat")) {
		SDL_LOG("WARNING: deprecated property scene.camera.lookat");

		const Property &prop = props.Get("scene.camera.lookat");
		orig.x = prop.Get<float>(0);
		orig.y = prop.Get<float>(1);
		orig.z = prop.Get<float>(2);
		target.x = prop.Get<float>(3);
		target.y = prop.Get<float>(4);
		target.z = prop.Get<float>(5);
		up = Vector(0.f, 0.f, 1.f);
	} else {
		if (!props.IsDefined("scene.camera.lookat.orig")) {
			// This is a trick I use from LuxCoreRenderer to set cameraToWorld to
			// identity matrix.
			//
			// I leave orig, target and up all set to (0.f, 0.f, 0.f)
		} else {
			orig = props.Get(Property("scene.camera.lookat.orig")(0.f, 10.f, 0.f)).Get<Point>();
			target = props.Get(Property("scene.camera.lookat.target")(0.f, 0.f, 0.f)).Get<Point>();
			up = props.Get(Property("scene.camera.up")(0.f, 0.f, 1.f)).Get<Vector>();
		}
	}

	const std::string type = props.Get(Property("scene.camera.type")("perspective")).Get<std::string>();

	SDL_LOG("Camera type: " << type);
	SDL_LOG("Camera position: " << orig);
	SDL_LOG("Camera target: " << target);

	auto_ptr<Camera> camera;
	if ((type == "orthographic") || (type == "perspective") || (type == "stereo")) {
		if (type == "orthographic") {
			OrthographicCamera *orthoCamera;

			if (props.IsDefined("scene.camera.screenwindow")) {
				float screenWindow[4];

				const Property &prop = props.Get(Property("scene.camera.screenwindow")(0.f, 1.f, 0.f, 1.f));
				screenWindow[0] = prop.Get<float>(0);
				screenWindow[1] = prop.Get<float>(1);
				screenWindow[2] = prop.Get<float>(2);
				screenWindow[3] = prop.Get<float>(3);

				orthoCamera = new OrthographicCamera(orig, target, up, &screenWindow[0]);
			} else
				orthoCamera = new OrthographicCamera(orig, target, up);

			camera.reset(orthoCamera);
		} else if (type == "perspective") {
			PerspectiveCamera *perspCamera;

			if (props.IsDefined("scene.camera.screenwindow")) {
				float screenWindow[4];

				const Property &prop = props.Get(Property("scene.camera.screenwindow")(0.f, 1.f, 0.f, 1.f));
				screenWindow[0] = prop.Get<float>(0);
				screenWindow[1] = prop.Get<float>(1);
				screenWindow[2] = prop.Get<float>(2);
				screenWindow[3] = prop.Get<float>(3);

				perspCamera = new PerspectiveCamera(orig, target, up, &screenWindow[0]);
			} else
				perspCamera = new PerspectiveCamera(orig, target, up);
			camera.reset(perspCamera);

			perspCamera->fieldOfView = props.Get(Property("scene.camera.fieldofview")(45.f)).Get<float>();
			perspCamera->enableOculusRiftBarrel = props.Get(Property("scene.camera.oculusrift.barrelpostpro.enable")(false)).Get<bool>();
		} else {
			StereoCamera *stereoCamera = new StereoCamera(orig, target, up);
			camera.reset(stereoCamera);

			stereoCamera->enableOculusRiftBarrel = props.Get(Property("scene.camera.oculusrift.barrelpostpro.enable")(false)).Get<bool>();
			stereoCamera->horizStereoEyesDistance = props.Get(Property("scene.camera.eyesdistance")(.0626f)).Get<float>();
			stereoCamera->horizStereoLensDistance = props.Get(Property("scene.camera.lensdistance")(.2779f)).Get<float>();
		}

		ProjectiveCamera *projCamera = (ProjectiveCamera *)camera.get();

		projCamera->lensRadius = props.Get(Property("scene.camera.lensradius")(0.f)).Get<float>();
		projCamera->focalDistance = props.Get(Property("scene.camera.focaldistance")(10.f)).Get<float>();
		projCamera->autoFocus = props.Get(Property("scene.camera.autofocus.enable")(false)).Get<bool>();

		// Check if I have to arbitrary clipping plane
		if (props.Get(Property("scene.camera.clippingplane.enable")(false)).Get<bool>()) {
			projCamera->clippingPlaneCenter = props.Get(Property("scene.camera.clippingplane.center")(Point())).Get<Point>();
			projCamera->clippingPlaneNormal = props.Get(Property("scene.camera.clippingplane.normal")(Normal())).Get<Normal>();
			projCamera->enableClippingPlane = true;
			SDL_LOG("Camera clipping plane enabled");
		} else {
			projCamera->enableClippingPlane = false;
			SDL_LOG("Camera clipping plane disabled");
		}
	} else
		throw runtime_error("Unknown camera type: " + type);

	camera->clipHither = props.Get(Property("scene.camera.cliphither")(1e-3f)).Get<float>();
	camera->clipYon = props.Get(Property("scene.camera.clipyon")(1e30f)).Get<float>();
	camera->shutterOpen = props.Get(Property("scene.camera.shutteropen")(0.f)).Get<float>();
	camera->shutterClose = props.Get(Property("scene.camera.shutterclose")(1.f)).Get<float>();

	// Check if I have to use a motion system
	if (props.IsDefined("scene.camera.motion.0.time")) {
		// Build the motion system
		vector<float> times;
		vector<Transform> transforms;
		for (u_int i =0;; ++i) {
			const string prefix = "scene.camera.motion." + ToString(i);
			if (!props.IsDefined(prefix +".time"))
				break;

			const float t = props.Get(prefix +".time").Get<float>();
			if (i > 0 && t <= times.back())
				throw runtime_error("Motion camera time must be monotonic");
			times.push_back(t);

			const Matrix4x4 mat = props.Get(Property(prefix +
				".transformation")(Matrix4x4::MAT_IDENTITY)).Get<Matrix4x4>();
			transforms.push_back(Transform(mat));
		}

		camera->motionSystem = new MotionSystem(times, transforms);
	}

	return camera.release();
}
<|endoftext|>


<commit_before>#include <bitcoin/utility/mmfile.hpp>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

namespace libbitcoin {

mmfile::mmfile(const std::string& filename)
{
    file_handle_ = open64(filename.c_str(),
        O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (file_handle_ == -1)
        return;
    struct stat64 sbuf;
    if (fstat64(file_handle_, &sbuf) == -1)
        return;
    size_ = (long long)sbuf.st_size;
    // You can static_cast void* pointers.
    data_ = static_cast<uint8_t*>(mmap64(
        0, size_, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
    if (data_ == MAP_FAILED)
        data_ = nullptr;
    // mmap opens its own file handle.
    close(file_handle_);
}
mmfile::~mmfile()
{
}

uint8_t* mmfile::data()
{
    return data_;
}
const uint8_t* mmfile::data() const
{
    return data_;
}
size_t mmfile::size() const
{
    return size_;
}

} // namespace libbitcoin

<commit_msg>Do not use 64-bit file IO calls in mmfile<commit_after>#include <bitcoin/utility/mmfile.hpp>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

namespace libbitcoin {

mmfile::mmfile(const std::string& filename)
{
    file_handle_ = open(filename.c_str(),
        O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (file_handle_ == -1)
        return;
    struct stat sbuf;
    if (fstat(file_handle_, &sbuf) == -1)
        return;
    size_ = (long long)sbuf.st_size;
    // You can static_cast void* pointers.
    data_ = static_cast<uint8_t*>(mmap(
        0, size_, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle_, 0));
    if (data_ == MAP_FAILED)
        data_ = nullptr;
    // mmap opens its own file handle.
    close(file_handle_);
}
mmfile::~mmfile()
{
}

uint8_t* mmfile::data()
{
    return data_;
}
const uint8_t* mmfile::data() const
{
    return data_;
}
size_t mmfile::size() const
{
    return size_;
}

} // namespace libbitcoin

<|endoftext|>


<commit_before>// This file is part of meshoptimizer library; see meshoptimizer.hpp for version/license details
#include "meshoptimizer.hpp"

#include <cassert>
#include <vector>

namespace meshopt
{

VertexCacheStatistics analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
{
	assert(index_count % 3 == 0);
	assert(cache_size >= 3);

	VertexCacheStatistics result = {};

	std::vector<unsigned int> cache_timestamps(vertex_count, 0);
	unsigned int timestamp = cache_size + 1;

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices[i];
		assert(index < vertex_count);

		if (timestamp - cache_timestamps[index] > cache_size)
		{
			// cache miss
			cache_timestamps[index] = timestamp++;
			result.vertices_transformed++;
		}
	}

	result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
	result.atvr = vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(vertex_count);

	return result;
}

} // namespace meshopt
<commit_msg>vcache: Add LRU cache analyzer<commit_after>// This file is part of meshoptimizer library; see meshoptimizer.hpp for version/license details
#include "meshoptimizer.hpp"

#include <cassert>
#include <algorithm>
#include <vector>

namespace meshopt
{

static VertexCacheStatistics analyzeVertexCacheFIFO(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
{
	assert(index_count % 3 == 0);
	assert(cache_size >= 3);

	VertexCacheStatistics result = {};

	std::vector<unsigned int> cache_timestamps(vertex_count, 0);
	unsigned int timestamp = cache_size + 1;

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices[i];
		assert(index < vertex_count);

		if (timestamp - cache_timestamps[index] > cache_size)
		{
			// cache miss
			cache_timestamps[index] = timestamp++;
			result.vertices_transformed++;
		}
	}

	result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
	result.atvr = vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(vertex_count);

	return result;
}

static VertexCacheStatistics analyzeVertexCacheLRU(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
{
	assert(index_count % 3 == 0);
	assert(cache_size >= 3);

	VertexCacheStatistics result = {};

	std::vector<unsigned int> cache;
	cache.reserve(cache_size + 1);

	for (size_t i = 0; i < index_count; ++i)
	{
		unsigned int index = indices[i];
		assert(index < vertex_count);

		std::vector<unsigned int>::iterator it = std::find(cache.begin(), cache.end(), index);

		if (it == cache.end())
			result.vertices_transformed++;
		else
			cache.erase(it);

		cache.push_back(index);

		if (cache.size() > cache_size)
			cache.erase(cache.begin(), cache.end() - cache_size);
	}

	result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
	result.atvr = vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(vertex_count);

	return result;
}

VertexCacheStatistics analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
{
	if (cache_size == 0)
		return analyzeVertexCacheLRU(indices, index_count, vertex_count, 16);
	else
		return analyzeVertexCacheFIFO(indices, index_count, vertex_count, cache_size);
}

} // namespace meshopt
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2020 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "cvar.h"

#include "utf8.h"

#define UTF_CPP_CPLUSPLUS 201703L
#include "third_party/utfcpp/source/utf8.h"

namespace utfcpp = utf8;

using u8_citer = utfcpp::iterator<std::string_view::const_iterator>;

namespace cvar {

cxxopts::Options options("xenia", "Xbox 360 Emulator");
std::map<std::string, ICommandVar*>* CmdVars;
std::map<std::string, IConfigVar*>* ConfigVars;
std::multimap<uint32_t, const IConfigVarUpdate*>* IConfigVarUpdate::updates_;

void PrintHelpAndExit() {
  std::cout << options.help({""}) << std::endl;
  std::cout << "For the full list of command line arguments, see xenia.cfg."
            << std::endl;
  exit(0);
}

void ParseLaunchArguments(int& argc, char**& argv,
                          const std::string_view positional_help,
                          const std::vector<std::string>& positional_options) {
  options.add_options()("help", "Prints help and exit.");

  if (!CmdVars) {
    CmdVars = new std::map<std::string, ICommandVar*>();
  }

  if (!ConfigVars) {
    ConfigVars = new std::map<std::string, IConfigVar*>();
  }

  for (auto& it : *CmdVars) {
    auto cmdVar = it.second;
    cmdVar->AddToLaunchOptions(&options);
  }

  for (const auto& it : *ConfigVars) {
    auto configVar = it.second;
    configVar->AddToLaunchOptions(&options);
  }

  try {
    options.positional_help(std::string(positional_help));
    options.parse_positional(positional_options);

    auto result = options.parse(argc, argv);
    if (result.count("help")) {
      PrintHelpAndExit();
    }

    for (auto& it : *CmdVars) {
      auto cmdVar = static_cast<ICommandVar*>(it.second);
      if (result.count(cmdVar->name())) {
        cmdVar->LoadFromLaunchOptions(&result);
      }
    }

    for (auto& it : *ConfigVars) {
      auto configVar = static_cast<IConfigVar*>(it.second);
      if (result.count(configVar->name())) {
        configVar->LoadFromLaunchOptions(&result);
      }
    }
  } catch (const cxxopts::OptionException& e) {
    std::cout << e.what() << std::endl;
    PrintHelpAndExit();
  }
}

namespace toml {

std::string EscapeBasicString(const std::string_view view) {
  std::string result;
  auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
  auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
  for (auto it = begin; it != end; ++it) {
    auto c = *it;
    if (c == '\b') {
      result += u8"\\b";
    } else if (c == '\t') {
      result += u8"\\t";
    } else if (c == '\n') {
      result += u8"\\n";
    } else if (c == '\f') {
      result += u8"\\f";
    } else if (c == '\r') {
      result += u8"\\r";
    } else if (c == '"') {
      result += u8"\\\"";
    } else if (c == '\\') {
      result += u8"\\\\";
    } else if (c < 0x20 || c == 0x7F) {
      if (c <= 0xFFFF) {
        result += fmt::format(u8"\\u{:04X}", c);
      } else {
        result += fmt::format(u8"\\u{:08X}", c);
      }
    } else {
      utfcpp::append(static_cast<char32_t>(c), result);
    }
  }
  return result;
}

std::string EscapeMultilineBasicString(const std::string_view view) {
  std::string result;
  int quote_run = 0;
  auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
  auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
  for (auto it = begin; it != end; ++it) {
    auto c = *it;
    if (quote_run > 0) {
      if (c == '"') {
        ++quote_run;
        continue;
      }
      for (int i = 0; i < quote_run; ++i) {
        if ((i % 3) == 2) {
          result += u8"\\";
        }
        result += u8"\"";
      }
      quote_run = 0;
    }
    if (c == '\b') {
      result += u8"\\b";
    } else if (c == '\t' || c == '\n') {
      result += c;
    } else if (c == '\f') {
      result += u8"\\f";
    } else if (c == '\r') {
      // Silently drop \r.
      // result += c;
    } else if (c == '"') {
      quote_run = 1;
    } else if (c == '\\') {
      result += u8"\\\\";
    } else if (c < 0x20 || c == 0x7F) {
      if (c <= 0xFFFF) {
        result += fmt::format(u8"\\u{:04X}", c);
      } else {
        result += fmt::format(u8"\\u{:08X}", c);
      }
    } else {
      utfcpp::append(static_cast<char32_t>(c), result);
    }
  }
  for (int i = 0; i < quote_run; ++i) {
    if ((i % 3) == 2) {
      result += u8"\\";
    }
    result += u8"\"";
  }
  return result;
}

std::string EscapeString(const std::string_view view) {
  const auto multiline_chars = std::string_view("\r\n");
  const auto escape_chars = std::string_view(
      "\0\b\v\f"
      "\x01\x02\x03\x04\x05\x06\x07\x0E\x0F"
      "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
      "'"
      "\x7F");

  if (xe::utf8::find_any_of(view, multiline_chars) == std::string_view::npos) {
    // single line
    if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) {
      return "'" + std::string(view) + "'";
    } else {
      return "\"" + toml::EscapeBasicString(view) + "\"";
    }
  } else {
    // multi line
    if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos &&
        xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) {
      return "'''\n" + std::string(view) + "'''";
    } else {
      return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\"";
    }
  }
}

}  // namespace toml

}  // namespace cvar
<commit_msg>[Base] Fix invalid cvar args causing silent exit.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2020 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "cvar.h"

#include "utf8.h"

#define UTF_CPP_CPLUSPLUS 201703L
#include "third_party/utfcpp/source/utf8.h"

#include "xenia/base/logging.h"
#include "xenia/base/main.h"

namespace utfcpp = utf8;

using u8_citer = utfcpp::iterator<std::string_view::const_iterator>;

namespace cvar {

cxxopts::Options options("xenia", "Xbox 360 Emulator");
std::map<std::string, ICommandVar*>* CmdVars;
std::map<std::string, IConfigVar*>* ConfigVars;
std::multimap<uint32_t, const IConfigVarUpdate*>* IConfigVarUpdate::updates_;

void PrintHelpAndExit() {
  std::cout << options.help({""}) << std::endl;
  std::cout << "For the full list of command line arguments, see xenia.cfg."
            << std::endl;
  exit(0);
}

void ParseLaunchArguments(int& argc, char**& argv,
                          const std::string_view positional_help,
                          const std::vector<std::string>& positional_options) {
  options.add_options()("help", "Prints help and exit.");

  if (!CmdVars) {
    CmdVars = new std::map<std::string, ICommandVar*>();
  }

  if (!ConfigVars) {
    ConfigVars = new std::map<std::string, IConfigVar*>();
  }

  for (auto& it : *CmdVars) {
    auto cmdVar = it.second;
    cmdVar->AddToLaunchOptions(&options);
  }

  for (const auto& it : *ConfigVars) {
    auto configVar = it.second;
    configVar->AddToLaunchOptions(&options);
  }

  try {
    options.positional_help(std::string(positional_help));
    options.parse_positional(positional_options);

    auto result = options.parse(argc, argv);
    if (result.count("help")) {
      if (xe::has_console_attached()) {
        PrintHelpAndExit();
      } else {
        xe::ShowInfoMessageBox(options.help({""}));
        exit(0);
      }
    }

    for (auto& it : *CmdVars) {
      auto cmdVar = static_cast<ICommandVar*>(it.second);
      if (result.count(cmdVar->name())) {
        cmdVar->LoadFromLaunchOptions(&result);
      }
    }

    for (auto& it : *ConfigVars) {
      auto configVar = static_cast<IConfigVar*>(it.second);
      if (result.count(configVar->name())) {
        configVar->LoadFromLaunchOptions(&result);
      }
    }
  } catch (const cxxopts::OptionException& e) {
    if (xe::has_console_attached()) {
      std::cout << e.what() << std::endl;
      PrintHelpAndExit();
    } else {
      std::string m =
          "Invalid launch options were given.\n" + options.help({""});
      xe::ShowErrorMessageBox(m);
      exit(0);
    }
  }
}

namespace toml {

std::string EscapeBasicString(const std::string_view view) {
  std::string result;
  auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
  auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
  for (auto it = begin; it != end; ++it) {
    auto c = *it;
    if (c == '\b') {
      result += u8"\\b";
    } else if (c == '\t') {
      result += u8"\\t";
    } else if (c == '\n') {
      result += u8"\\n";
    } else if (c == '\f') {
      result += u8"\\f";
    } else if (c == '\r') {
      result += u8"\\r";
    } else if (c == '"') {
      result += u8"\\\"";
    } else if (c == '\\') {
      result += u8"\\\\";
    } else if (c < 0x20 || c == 0x7F) {
      if (c <= 0xFFFF) {
        result += fmt::format(u8"\\u{:04X}", c);
      } else {
        result += fmt::format(u8"\\u{:08X}", c);
      }
    } else {
      utfcpp::append(static_cast<char32_t>(c), result);
    }
  }
  return result;
}

std::string EscapeMultilineBasicString(const std::string_view view) {
  std::string result;
  int quote_run = 0;
  auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
  auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
  for (auto it = begin; it != end; ++it) {
    auto c = *it;
    if (quote_run > 0) {
      if (c == '"') {
        ++quote_run;
        continue;
      }
      for (int i = 0; i < quote_run; ++i) {
        if ((i % 3) == 2) {
          result += u8"\\";
        }
        result += u8"\"";
      }
      quote_run = 0;
    }
    if (c == '\b') {
      result += u8"\\b";
    } else if (c == '\t' || c == '\n') {
      result += c;
    } else if (c == '\f') {
      result += u8"\\f";
    } else if (c == '\r') {
      // Silently drop \r.
      // result += c;
    } else if (c == '"') {
      quote_run = 1;
    } else if (c == '\\') {
      result += u8"\\\\";
    } else if (c < 0x20 || c == 0x7F) {
      if (c <= 0xFFFF) {
        result += fmt::format(u8"\\u{:04X}", c);
      } else {
        result += fmt::format(u8"\\u{:08X}", c);
      }
    } else {
      utfcpp::append(static_cast<char32_t>(c), result);
    }
  }
  for (int i = 0; i < quote_run; ++i) {
    if ((i % 3) == 2) {
      result += u8"\\";
    }
    result += u8"\"";
  }
  return result;
}

std::string EscapeString(const std::string_view view) {
  const auto multiline_chars = std::string_view("\r\n");
  const auto escape_chars = std::string_view(
      "\0\b\v\f"
      "\x01\x02\x03\x04\x05\x06\x07\x0E\x0F"
      "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
      "'"
      "\x7F");

  if (xe::utf8::find_any_of(view, multiline_chars) == std::string_view::npos) {
    // single line
    if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) {
      return "'" + std::string(view) + "'";
    } else {
      return "\"" + toml::EscapeBasicString(view) + "\"";
    }
  } else {
    // multi line
    if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos &&
        xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) {
      return "'''\n" + std::string(view) + "'''";
    } else {
      return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\"";
    }
  }
}

}  // namespace toml

}  // namespace cvar
<|endoftext|>


<commit_before>
#include "xml3d_exporter.h"
#include "logger.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <assimp/../../code/BoostWorkaround/boost/lexical_cast.hpp>

namespace {
	void ExportScene(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
}

Assimp::Exporter::ExportFormatEntry Assimp2XML3D_desc = Assimp::Exporter::ExportFormatEntry(
	"xml",
	"XML representation of the scene, compatible for use with XML3D as an external asset.",
	"xml",
	ExportScene,
	0u);

namespace {
	void ExportScene(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) {
		XML3DExporter exp(scene, file);
		exp.Export();
		exp.writeFile();
	}
}

XML3DExporter::XML3DExporter(const aiScene* ai, const char* file) {
	aiCopyScene(ai, &scene);
	filename = file;
}

XML3DExporter::~XML3DExporter() {
	doc.Clear();
	aiFreeScene(scene);
}

void XML3DExporter::Export() {
	tinyxml2::XMLElement* xml3d = doc.NewElement("xml3d");
	tinyxml2::XMLElement* defs = doc.NewElement("defs");
	tinyxml2::XMLElement* asset = doc.NewElement("asset");
	xml3d->InsertFirstChild(defs);
	xml3d->LinkEndChild(asset);
	doc.InsertFirstChild(xml3d);

	std::string id(filename);
	id = id.substr(0, id.find_first_of('.'));
	asset->SetAttribute("id", id.c_str());

	if (scene->HasMeshes()) {
		for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
			Export(asset, scene->mMeshes[i]);
		}
	}

	if (scene->HasMaterials()) {
		for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
			Export(defs, scene->mMaterials[i]);
		}
	}

	// Flatten scene hierarchy into a list of assetmeshes
	Export(asset, scene->mRootNode, &aiMatrix4x4());
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiNode* an, aiMatrix4x4* parentTransform) {
	// Flatten all non-mesh nodes while gathering the transformations

	aiMatrix4x4 t(an->mTransformation);
	t = *parentTransform * t;

	for (unsigned int i = 0; i < an->mNumMeshes; i++) {
		Export(parent, scene->mMeshes[an->mMeshes[i]], &t);
	}

	for (unsigned int i = 0; i < an->mNumChildren; i++) {
		Export(parent, an->mChildren[i], &t);
	}
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiMesh* am, aiMatrix4x4* parentTransform) {
	tinyxml2::XMLElement* mesh = doc.NewElement("assetmesh");
	tinyxml2::XMLElement* tmat = doc.NewElement("float4x4");

	mesh->SetAttribute("includes", am->mName.C_Str());
	mesh->SetAttribute("type", "triangles");
	tmat->SetAttribute("name", "meshTransform");
	tmat->SetText(toXml3dString(parentTransform).c_str());

	aiMaterial* mat = scene->mMaterials[am->mMaterialIndex];
	aiString name;
	mat->Get(AI_MATKEY_NAME, name);
	mat->AddProperty(&name, AI_MATKEY_NAME);

	std::string namestr("#");
	namestr.append(name.C_Str());
	mesh->SetAttribute("material", namestr.c_str());

	mesh->LinkEndChild(tmat);
	parent->LinkEndChild(mesh);
}

void XML3DExporter::Export(tinyxml2::XMLElement* asset, aiMesh* am) {
	tinyxml2::XMLElement* data = doc.NewElement("assetdata");
	stringToHTMLId(&am->mName);
	data->SetAttribute("name", am->mName.C_Str());

	//Export indices
	tinyxml2::XMLElement* index = doc.NewElement("int");
	index->SetAttribute("name", "index");
	index->SetText(toXml3dString(am->mFaces, am->mNumFaces).c_str());
	data->LinkEndChild(index);

	//Export positions
	tinyxml2::XMLElement* pos = doc.NewElement("float3");
	pos->SetAttribute("name", "position");
	pos->SetText(toXml3dString(am->mVertices, am->mNumVertices).c_str());
	data->LinkEndChild(pos);

	//Export normals
	if (am->HasNormals()) {
		tinyxml2::XMLElement* norm = doc.NewElement("float3");
		norm->SetAttribute("name", "normal");
		norm->SetText(toXml3dString(am->mNormals, am->mNumVertices).c_str());
		data->LinkEndChild(norm);
	}

	//Export texcoords
	if (am->GetNumUVChannels()) {
		tinyxml2::XMLElement* tc = doc.NewElement("float2");
		tc->SetAttribute("name", "texcoord");
		// TODO: UV channel selection
		tc->SetText(toXml3dString(am->mTextureCoords[0], am->mNumVertices, true).c_str());
		data->LinkEndChild(tc);
	}

	//Export colors
	if (am->GetNumColorChannels()) {
		tinyxml2::XMLElement* color = doc.NewElement("float3");
		color->SetAttribute("name", "color");
		// TODO: Color channel selection
		color->SetText(toXml3dString(am->mColors[0], am->mNumVertices, true).c_str());
		data->LinkEndChild(color);
	}

	asset->InsertFirstChild(data);
}

void XML3DExporter::Export(tinyxml2::XMLElement* defs, aiMaterial* amat) {
	tinyxml2::XMLElement* material = doc.NewElement("material");
	aiString name;
	amat->Get(AI_MATKEY_NAME, name);
	stringToHTMLId(&name);
	material->SetAttribute("id", name.C_Str());
	material->SetAttribute("script", "urn:xml3d:material:phong"); //TODO: Choose right shading model

	// For now we only handle properties that the default XML3D material shaders can work with
	tinyxml2::XMLElement* diffuseColor = doc.NewElement("float3");
	diffuseColor->SetAttribute("name", "diffuseColor");
	aiColor4D dColor;
	amat->Get(AI_MATKEY_COLOR_DIFFUSE, dColor);
	diffuseColor->SetText(toXml3dString(&dColor, 1, true).c_str());
	material->LinkEndChild(diffuseColor);

	tinyxml2::XMLElement* specularColor = doc.NewElement("float3");
	specularColor->SetAttribute("name", "specularColor");
	aiColor4D sColor;
	amat->Get(AI_MATKEY_COLOR_SPECULAR, sColor);
	specularColor->SetText(toXml3dString(&sColor, 1, true).c_str());
	material->LinkEndChild(specularColor);

	tinyxml2::XMLElement* emissiveColor = doc.NewElement("float3");
	emissiveColor->SetAttribute("name", "emissiveColor");
	aiColor4D eColor;
	amat->Get(AI_MATKEY_COLOR_EMISSIVE, eColor);
	emissiveColor->SetText(toXml3dString(&eColor, 1, true).c_str());
	material->LinkEndChild(emissiveColor);

	tinyxml2::XMLElement* shininess = doc.NewElement("float");
	shininess->SetAttribute("name", "shininess");
	float s;
	amat->Get(AI_MATKEY_SHININESS, s);
	shininess->SetText(boost::lexical_cast<std::string>(s).c_str());
	material->LinkEndChild(shininess);

	tinyxml2::XMLElement* opacity = doc.NewElement("float");
	opacity->SetAttribute("name", "transparency");
	float o;
	amat->Get(AI_MATKEY_OPACITY, o);
	opacity->SetText(boost::lexical_cast<std::string>(1 - o).c_str());
	material->LinkEndChild(opacity);

	defs->LinkEndChild(material);
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiTexture* at) {

}

void XML3DExporter::writeFile() {
	doc.SaveFile(filename);
}

std::string XML3DExporter::toXml3dString(aiMatrix4x4* m) {
	std::stringstream ss;
	ss  << m->a1 << ' ' << m->b1 << ' ' << m->c1 << ' ' << m->d1 << ' '
		<< m->a2 << ' ' << m->b2 << ' ' << m->c2 << ' ' << m->d2 << ' '
		<< m->a3 << ' ' << m->b3 << ' ' << m->c3 << ' ' << m->d3 << ' '
		<< m->a4 << ' ' << m->b4 << ' ' << m->c4 << ' ' << m->d4 << ' ';
	std::string str = ss.str();
	if (str.find("NAN") != std::string::npos) {
		Logger::Warn("Invalid transformation matrix, replacing with Identity: [" + str + "]");
		return toXml3dString(&aiMatrix4x4());
	}
	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiVector3D* v, unsigned int numVertices, bool toVec2) {
	std::stringstream ss;
	if (toVec2) { // Special case for texture coordinates, vec3 in assimp -> vec2 in xml3d
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].x << ' ' << v[i].y << ' ';
		}
	}
	else {
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].x << ' ' << v[i].y << ' ' << v[i].z << ' ';
		}
	}

	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiColor4D* v, unsigned int numVertices, bool toVec3) {
	std::stringstream ss;
	if (toVec3) { // Drop the alpha component as XML3D expects only RGB
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].r << ' ' << v[i].g << ' ' << v[i].b << ' ';
		}
	}
	else {
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].r << ' ' << v[i].g << ' ' << v[i].b << ' ' << v[i].a << ' ';
		}
	}

	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiFace* f, unsigned int numFaces) {
	std::stringstream ss;
	for (unsigned int i = 0; i < numFaces; i++) {
		ss << f[i].mIndices[0] << ' ' << f[i].mIndices[1] << ' ' << f[i].mIndices[2] << ' ';
	}

	return ss.str();
}

void XML3DExporter::stringToHTMLId(aiString* ai) {
	// Ensure the name is not empty and is safe to use as an HTML5 id string
	std::string str(ai->C_Str());

	if (!(str.length() > 0)) {
		str = "_Generated_Name_" + boost::lexical_cast<std::string>(mChangedNamesCounter++);
	}
	if (str.find_first_of(' ') != std::string::npos) {
		std::replace(str.begin(), str.end(), ' ', '_');
	}
	if (usedNames.count(str) > 0) {
		str += "_" + boost::lexical_cast<std::string>(mChangedNamesCounter++);
	}
	usedNames.emplace(str, 'x');

	ai->Set(str);
}

<commit_msg>Log a warning when a duplicate name was encountered<commit_after>
#include "xml3d_exporter.h"
#include "logger.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <assimp/../../code/BoostWorkaround/boost/lexical_cast.hpp>

namespace {
	void ExportScene(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
}

Assimp::Exporter::ExportFormatEntry Assimp2XML3D_desc = Assimp::Exporter::ExportFormatEntry(
	"xml",
	"XML representation of the scene, compatible for use with XML3D as an external asset.",
	"xml",
	ExportScene,
	0u);

namespace {
	void ExportScene(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) {
		XML3DExporter exp(scene, file);
		exp.Export();
		exp.writeFile();
	}
}

XML3DExporter::XML3DExporter(const aiScene* ai, const char* file) {
	aiCopyScene(ai, &scene);
	filename = file;
}

XML3DExporter::~XML3DExporter() {
	doc.Clear();
	aiFreeScene(scene);
}

void XML3DExporter::Export() {
	tinyxml2::XMLElement* xml3d = doc.NewElement("xml3d");
	tinyxml2::XMLElement* defs = doc.NewElement("defs");
	tinyxml2::XMLElement* asset = doc.NewElement("asset");
	xml3d->InsertFirstChild(defs);
	xml3d->LinkEndChild(asset);
	doc.InsertFirstChild(xml3d);

	std::string id(filename);
	id = id.substr(0, id.find_first_of('.'));
	asset->SetAttribute("id", id.c_str());

	if (scene->HasMeshes()) {
		for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
			Export(asset, scene->mMeshes[i]);
		}
	}

	if (scene->HasMaterials()) {
		for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
			Export(defs, scene->mMaterials[i]);
		}
	}

	// Flatten scene hierarchy into a list of assetmeshes
	Export(asset, scene->mRootNode, &aiMatrix4x4());
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiNode* an, aiMatrix4x4* parentTransform) {
	// Flatten all non-mesh nodes while gathering the transformations

	aiMatrix4x4 t(an->mTransformation);
	t = *parentTransform * t;

	for (unsigned int i = 0; i < an->mNumMeshes; i++) {
		Export(parent, scene->mMeshes[an->mMeshes[i]], &t);
	}

	for (unsigned int i = 0; i < an->mNumChildren; i++) {
		Export(parent, an->mChildren[i], &t);
	}
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiMesh* am, aiMatrix4x4* parentTransform) {
	tinyxml2::XMLElement* mesh = doc.NewElement("assetmesh");
	tinyxml2::XMLElement* tmat = doc.NewElement("float4x4");

	mesh->SetAttribute("includes", am->mName.C_Str());
	mesh->SetAttribute("type", "triangles");
	tmat->SetAttribute("name", "meshTransform");
	tmat->SetText(toXml3dString(parentTransform).c_str());

	aiMaterial* mat = scene->mMaterials[am->mMaterialIndex];
	aiString name;
	mat->Get(AI_MATKEY_NAME, name);
	mat->AddProperty(&name, AI_MATKEY_NAME);

	std::string namestr("#");
	namestr.append(name.C_Str());
	mesh->SetAttribute("material", namestr.c_str());

	mesh->LinkEndChild(tmat);
	parent->LinkEndChild(mesh);
}

void XML3DExporter::Export(tinyxml2::XMLElement* asset, aiMesh* am) {
	tinyxml2::XMLElement* data = doc.NewElement("assetdata");
	stringToHTMLId(&am->mName);
	data->SetAttribute("name", am->mName.C_Str());

	//Export indices
	tinyxml2::XMLElement* index = doc.NewElement("int");
	index->SetAttribute("name", "index");
	index->SetText(toXml3dString(am->mFaces, am->mNumFaces).c_str());
	data->LinkEndChild(index);

	//Export positions
	tinyxml2::XMLElement* pos = doc.NewElement("float3");
	pos->SetAttribute("name", "position");
	pos->SetText(toXml3dString(am->mVertices, am->mNumVertices).c_str());
	data->LinkEndChild(pos);

	//Export normals
	if (am->HasNormals()) {
		tinyxml2::XMLElement* norm = doc.NewElement("float3");
		norm->SetAttribute("name", "normal");
		norm->SetText(toXml3dString(am->mNormals, am->mNumVertices).c_str());
		data->LinkEndChild(norm);
	}

	//Export texcoords
	if (am->GetNumUVChannels()) {
		tinyxml2::XMLElement* tc = doc.NewElement("float2");
		tc->SetAttribute("name", "texcoord");
		// TODO: UV channel selection
		tc->SetText(toXml3dString(am->mTextureCoords[0], am->mNumVertices, true).c_str());
		data->LinkEndChild(tc);
	}

	//Export colors
	if (am->GetNumColorChannels()) {
		tinyxml2::XMLElement* color = doc.NewElement("float3");
		color->SetAttribute("name", "color");
		// TODO: Color channel selection
		color->SetText(toXml3dString(am->mColors[0], am->mNumVertices, true).c_str());
		data->LinkEndChild(color);
	}

	asset->InsertFirstChild(data);
}

void XML3DExporter::Export(tinyxml2::XMLElement* defs, aiMaterial* amat) {
	tinyxml2::XMLElement* material = doc.NewElement("material");
	aiString name;
	amat->Get(AI_MATKEY_NAME, name);
	stringToHTMLId(&name);
	material->SetAttribute("id", name.C_Str());
	material->SetAttribute("script", "urn:xml3d:material:phong"); //TODO: Choose right shading model

	// For now we only handle properties that the default XML3D material shaders can work with
	tinyxml2::XMLElement* diffuseColor = doc.NewElement("float3");
	diffuseColor->SetAttribute("name", "diffuseColor");
	aiColor4D dColor;
	amat->Get(AI_MATKEY_COLOR_DIFFUSE, dColor);
	diffuseColor->SetText(toXml3dString(&dColor, 1, true).c_str());
	material->LinkEndChild(diffuseColor);

	tinyxml2::XMLElement* specularColor = doc.NewElement("float3");
	specularColor->SetAttribute("name", "specularColor");
	aiColor4D sColor;
	amat->Get(AI_MATKEY_COLOR_SPECULAR, sColor);
	specularColor->SetText(toXml3dString(&sColor, 1, true).c_str());
	material->LinkEndChild(specularColor);

	tinyxml2::XMLElement* emissiveColor = doc.NewElement("float3");
	emissiveColor->SetAttribute("name", "emissiveColor");
	aiColor4D eColor;
	amat->Get(AI_MATKEY_COLOR_EMISSIVE, eColor);
	emissiveColor->SetText(toXml3dString(&eColor, 1, true).c_str());
	material->LinkEndChild(emissiveColor);

	tinyxml2::XMLElement* shininess = doc.NewElement("float");
	shininess->SetAttribute("name", "shininess");
	float s;
	amat->Get(AI_MATKEY_SHININESS, s);
	shininess->SetText(boost::lexical_cast<std::string>(s).c_str());
	material->LinkEndChild(shininess);

	tinyxml2::XMLElement* opacity = doc.NewElement("float");
	opacity->SetAttribute("name", "transparency");
	float o;
	amat->Get(AI_MATKEY_OPACITY, o);
	opacity->SetText(boost::lexical_cast<std::string>(1 - o).c_str());
	material->LinkEndChild(opacity);

	defs->LinkEndChild(material);
}

void XML3DExporter::Export(tinyxml2::XMLElement* parent, aiTexture* at) {

}

void XML3DExporter::writeFile() {
	doc.SaveFile(filename);
}

std::string XML3DExporter::toXml3dString(aiMatrix4x4* m) {
	std::stringstream ss;
	ss  << m->a1 << ' ' << m->b1 << ' ' << m->c1 << ' ' << m->d1 << ' '
		<< m->a2 << ' ' << m->b2 << ' ' << m->c2 << ' ' << m->d2 << ' '
		<< m->a3 << ' ' << m->b3 << ' ' << m->c3 << ' ' << m->d3 << ' '
		<< m->a4 << ' ' << m->b4 << ' ' << m->c4 << ' ' << m->d4 << ' ';
	std::string str = ss.str();
	if (str.find("NAN") != std::string::npos) {
		Logger::Warn("Invalid transformation matrix, replacing with Identity: [" + str + "]");
		return toXml3dString(&aiMatrix4x4());
	}
	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiVector3D* v, unsigned int numVertices, bool toVec2) {
	std::stringstream ss;
	if (toVec2) { // Special case for texture coordinates, vec3 in assimp -> vec2 in xml3d
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].x << ' ' << v[i].y << ' ';
		}
	}
	else {
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].x << ' ' << v[i].y << ' ' << v[i].z << ' ';
		}
	}

	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiColor4D* v, unsigned int numVertices, bool toVec3) {
	std::stringstream ss;
	if (toVec3) { // Drop the alpha component as XML3D expects only RGB
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].r << ' ' << v[i].g << ' ' << v[i].b << ' ';
		}
	}
	else {
		for (unsigned int i = 0; i < numVertices; i++) {
			ss << v[i].r << ' ' << v[i].g << ' ' << v[i].b << ' ' << v[i].a << ' ';
		}
	}

	return ss.str();
}

std::string XML3DExporter::toXml3dString(aiFace* f, unsigned int numFaces) {
	std::stringstream ss;
	for (unsigned int i = 0; i < numFaces; i++) {
		ss << f[i].mIndices[0] << ' ' << f[i].mIndices[1] << ' ' << f[i].mIndices[2] << ' ';
	}

	return ss.str();
}

void XML3DExporter::stringToHTMLId(aiString* ai) {
	// Ensure the name is not empty and is safe to use as an HTML5 id string
	std::string str(ai->C_Str());

	if (!(str.length() > 0)) {
		str = "_Generated_Name_" + boost::lexical_cast<std::string>(mChangedNamesCounter++);
	}
	if (str.find_first_of(' ') != std::string::npos) {
		std::replace(str.begin(), str.end(), ' ', '_');
	}
	if (usedNames.count(str) > 0) {
		str += "_" + boost::lexical_cast<std::string>(mChangedNamesCounter++);
		Logger::Warn("Renamed '" + str.substr(0, str.find_last_of("_")) + "' to '" + str + "' to avoid duplicate IDs");
	}
	usedNames.emplace(str, 'x');

	ai->Set(str);
}

<|endoftext|>


<commit_before>// Copyright (c) 2013 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 "ui/message_center/views/message_popup_collection.h"

#include <set>

#include "base/bind.h"
#include "base/timer.h"
#include "ui/gfx/screen.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/notification_view.h"
#include "ui/views/background.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace message_center {

class ToastContentsView : public views::WidgetDelegateView {
 public:
  ToastContentsView(const Notification* notification,
                    MessagePopupCollection* collection)
      : collection_(collection) {
    DCHECK(collection_);

    set_notify_enter_exit_on_child(true);
    SetLayoutManager(new views::FillLayout());
    // Sets the transparent background. Then, when the message view is slid out,
    // the whole toast seems to slide although the actual bound of the widget
    // remains. This is hacky but easier to keep the consistency.
    set_background(views::Background::CreateSolidBackground(0, 0, 0, 0));

    int seconds = kAutocloseDefaultDelaySeconds;
    if (notification->priority() > DEFAULT_PRIORITY)
      seconds = kAutocloseHighPriorityDelaySeconds;
    delay_ = base::TimeDelta::FromSeconds(seconds);
  }

  views::Widget* CreateWidget(gfx::NativeView context) {
    views::Widget::InitParams params(
        views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    params.keep_on_top = true;
    params.context = context;
    params.transparent = true;
    // The origin of the initial bounds are set to (0, 0). It'll then moved by
    // MessagePopupCollection.
    params.bounds = gfx::Rect(
        gfx::Size(kWebNotificationWidth,
                  GetHeightForWidth(kWebNotificationWidth)));
    params.delegate = this;
    views::Widget* widget = new views::Widget();
    widget->Init(params);
    return widget;
  }

  void SetContents(MessageView* view) {
    RemoveAllChildViews(true);
    AddChildView(view);
    views::Widget* widget = GetWidget();
    if (widget) {
      gfx::Rect bounds = widget->GetWindowBoundsInScreen();
      bounds.set_height(view->GetHeightForWidth(kWebNotificationWidth));
      widget->SetBounds(bounds);
    }
    Layout();
  }

  void SuspendTimer() {
    timer_.Reset();
  }

  void RestartTimer() {
    base::TimeDelta passed = base::Time::Now() - start_time_;
    if (passed > delay_) {
      GetWidget()->Close();
    } else {
      delay_ -= passed;
      StartTimer();
    }
  }

  void StartTimer() {
    start_time_ = base::Time::Now();
    timer_.Start(FROM_HERE,
                 delay_,
                 base::Bind(&views::Widget::Close,
                            base::Unretained(GetWidget())));
  }

  // Overridden from views::WidgetDelegate:
  virtual views::View* GetContentsView() OVERRIDE {
    return this;
  }

  virtual void WindowClosing() OVERRIDE {
    if (timer_.IsRunning())
      SuspendTimer();
  }

  virtual bool CanActivate() const OVERRIDE {
    return false;
  }

  // Overridden from views::View:
  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
    collection_->OnMouseEntered();
  }

  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
    collection_->OnMouseExited();
  }

 private:
  base::TimeDelta delay_;
  base::Time start_time_;
  base::OneShotTimer<views::Widget> timer_;
  MessagePopupCollection* collection_;

  DISALLOW_COPY_AND_ASSIGN(ToastContentsView);
};

MessagePopupCollection::MessagePopupCollection(gfx::NativeView context,
                                               MessageCenter* message_center)
    : context_(context),
      message_center_(message_center) {
  DCHECK(message_center_);
}

MessagePopupCollection::~MessagePopupCollection() {
  CloseAllWidgets();
}

void MessagePopupCollection::UpdatePopups() {
  NotificationList::PopupNotifications popups =
      message_center_->notification_list()->GetPopupNotifications();

  if (popups.empty()) {
    CloseAllWidgets();
    return;
  }

  gfx::Screen* screen = gfx::Screen::GetScreenFor(context_);
  gfx::Rect work_area = screen->GetDisplayNearestWindow(context_).work_area();

  std::set<std::string> old_toast_ids;
  for (ToastContainer::iterator iter = toasts_.begin(); iter != toasts_.end();
       ++iter) {
    old_toast_ids.insert(iter->first);
  }

  int bottom = work_area.bottom() - kMarginBetweenItems;
  int left = work_area.right() - kWebNotificationWidth - kMarginBetweenItems;
  // Iterate in the reverse order to keep the oldest toasts on screen. Newer
  // items may be ignored if there are no room to place them.
  for (NotificationList::PopupNotifications::const_reverse_iterator iter =
           popups.rbegin(); iter != popups.rend(); ++iter) {
    MessageView* view =
        NotificationView::Create(*(*iter), message_center_, true);
    int view_height = view->GetHeightForWidth(kWebNotificationWidth);
    if (bottom - view_height - kMarginBetweenItems < 0) {
      delete view;
      break;
    }

    ToastContainer::iterator toast_iter = toasts_.find((*iter)->id());
    views::Widget* widget = NULL;
    if (toast_iter != toasts_.end()) {
      widget = toast_iter->second->GetWidget();
      old_toast_ids.erase((*iter)->id());
      // Need to replace the contents because |view| can be updated, like
      // image loads.
      toast_iter->second->SetContents(view);
    } else {
      ToastContentsView* toast = new ToastContentsView(*iter, this);
      toast->SetContents(view);
      widget = toast->CreateWidget(context_);
      widget->AddObserver(this);
      toast->StartTimer();
      toasts_[(*iter)->id()] = toast;
    }

    // Place/move the toast widgets. Currently it stacks the widgets from the
    // right-bottom of the work area.
    // TODO(mukai): allow to specify the placement policy from outside of this
    // class. The policy should be specified from preference on Windows, or
    // the launcher alignment on ChromeOS.
    if (widget) {
      gfx::Rect bounds(widget->GetWindowBoundsInScreen());
      bounds.set_origin(gfx::Point(left, bottom - bounds.height()));
      widget->SetBounds(bounds);
      if (!widget->IsVisible())
        widget->Show();
    }

    bottom -= view_height + kMarginBetweenItems;
  }

  for (std::set<std::string>::const_iterator iter = old_toast_ids.begin();
       iter != old_toast_ids.end(); ++iter) {
    ToastContainer::iterator toast_iter = toasts_.find(*iter);
    DCHECK(toast_iter != toasts_.end());
    views::Widget* widget = toast_iter->second->GetWidget();
    widget->RemoveObserver(this);
    widget->Close();
    toasts_.erase(toast_iter);
  }
}

void MessagePopupCollection::OnMouseEntered() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->SuspendTimer();
  }
}

void MessagePopupCollection::OnMouseExited() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->RestartTimer();
  }
}

void MessagePopupCollection::CloseAllWidgets() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->SuspendTimer();
    views::Widget* widget = iter->second->GetWidget();
    widget->RemoveObserver(this);
    widget->Close();
  }
  toasts_.clear();
}

void MessagePopupCollection::OnWidgetDestroying(views::Widget* widget) {
  widget->RemoveObserver(this);
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    if (iter->second->GetWidget() == widget) {
      message_center_->notification_list()->MarkSinglePopupAsShown(
          iter->first, false);
      toasts_.erase(iter);
      break;
    }
  }
  UpdatePopups();
}

}  // namespace message_center
<commit_msg>Don't steal focus with the new popup collection.<commit_after>// Copyright (c) 2013 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 "ui/message_center/views/message_popup_collection.h"

#include <set>

#include "base/bind.h"
#include "base/timer.h"
#include "ui/gfx/screen.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/notification_view.h"
#include "ui/views/background.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace message_center {

class ToastContentsView : public views::WidgetDelegateView {
 public:
  ToastContentsView(const Notification* notification,
                    MessagePopupCollection* collection)
      : collection_(collection) {
    DCHECK(collection_);

    set_notify_enter_exit_on_child(true);
    SetLayoutManager(new views::FillLayout());
    // Sets the transparent background. Then, when the message view is slid out,
    // the whole toast seems to slide although the actual bound of the widget
    // remains. This is hacky but easier to keep the consistency.
    set_background(views::Background::CreateSolidBackground(0, 0, 0, 0));

    int seconds = kAutocloseDefaultDelaySeconds;
    if (notification->priority() > DEFAULT_PRIORITY)
      seconds = kAutocloseHighPriorityDelaySeconds;
    delay_ = base::TimeDelta::FromSeconds(seconds);
  }

  views::Widget* CreateWidget(gfx::NativeView context) {
    views::Widget::InitParams params(
        views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    params.keep_on_top = true;
    params.context = context;
    params.transparent = true;
    // The origin of the initial bounds are set to (0, 0). It'll then moved by
    // MessagePopupCollection.
    params.bounds = gfx::Rect(
        gfx::Size(kWebNotificationWidth,
                  GetHeightForWidth(kWebNotificationWidth)));
    params.delegate = this;
    views::Widget* widget = new views::Widget();
    widget->set_focus_on_creation(false);
    widget->Init(params);
    return widget;
  }

  void SetContents(MessageView* view) {
    RemoveAllChildViews(true);
    AddChildView(view);
    views::Widget* widget = GetWidget();
    if (widget) {
      gfx::Rect bounds = widget->GetWindowBoundsInScreen();
      bounds.set_height(view->GetHeightForWidth(kWebNotificationWidth));
      widget->SetBounds(bounds);
    }
    Layout();
  }

  void SuspendTimer() {
    timer_.Reset();
  }

  void RestartTimer() {
    base::TimeDelta passed = base::Time::Now() - start_time_;
    if (passed > delay_) {
      GetWidget()->Close();
    } else {
      delay_ -= passed;
      StartTimer();
    }
  }

  void StartTimer() {
    start_time_ = base::Time::Now();
    timer_.Start(FROM_HERE,
                 delay_,
                 base::Bind(&views::Widget::Close,
                            base::Unretained(GetWidget())));
  }

  // Overridden from views::WidgetDelegate:
  virtual views::View* GetContentsView() OVERRIDE {
    return this;
  }

  virtual void WindowClosing() OVERRIDE {
    if (timer_.IsRunning())
      SuspendTimer();
  }

  virtual bool CanActivate() const OVERRIDE {
    return false;
  }

  // Overridden from views::View:
  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
    collection_->OnMouseEntered();
  }

  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
    collection_->OnMouseExited();
  }

 private:
  base::TimeDelta delay_;
  base::Time start_time_;
  base::OneShotTimer<views::Widget> timer_;
  MessagePopupCollection* collection_;

  DISALLOW_COPY_AND_ASSIGN(ToastContentsView);
};

MessagePopupCollection::MessagePopupCollection(gfx::NativeView context,
                                               MessageCenter* message_center)
    : context_(context),
      message_center_(message_center) {
  DCHECK(message_center_);
}

MessagePopupCollection::~MessagePopupCollection() {
  CloseAllWidgets();
}

void MessagePopupCollection::UpdatePopups() {
  NotificationList::PopupNotifications popups =
      message_center_->notification_list()->GetPopupNotifications();

  if (popups.empty()) {
    CloseAllWidgets();
    return;
  }

  gfx::Screen* screen = gfx::Screen::GetScreenFor(context_);
  gfx::Rect work_area = screen->GetDisplayNearestWindow(context_).work_area();

  std::set<std::string> old_toast_ids;
  for (ToastContainer::iterator iter = toasts_.begin(); iter != toasts_.end();
       ++iter) {
    old_toast_ids.insert(iter->first);
  }

  int bottom = work_area.bottom() - kMarginBetweenItems;
  int left = work_area.right() - kWebNotificationWidth - kMarginBetweenItems;
  // Iterate in the reverse order to keep the oldest toasts on screen. Newer
  // items may be ignored if there are no room to place them.
  for (NotificationList::PopupNotifications::const_reverse_iterator iter =
           popups.rbegin(); iter != popups.rend(); ++iter) {
    MessageView* view =
        NotificationView::Create(*(*iter), message_center_, true);
    int view_height = view->GetHeightForWidth(kWebNotificationWidth);
    if (bottom - view_height - kMarginBetweenItems < 0) {
      delete view;
      break;
    }

    ToastContainer::iterator toast_iter = toasts_.find((*iter)->id());
    views::Widget* widget = NULL;
    if (toast_iter != toasts_.end()) {
      widget = toast_iter->second->GetWidget();
      old_toast_ids.erase((*iter)->id());
      // Need to replace the contents because |view| can be updated, like
      // image loads.
      toast_iter->second->SetContents(view);
    } else {
      ToastContentsView* toast = new ToastContentsView(*iter, this);
      toast->SetContents(view);
      widget = toast->CreateWidget(context_);
      widget->AddObserver(this);
      toast->StartTimer();
      toasts_[(*iter)->id()] = toast;
    }

    // Place/move the toast widgets. Currently it stacks the widgets from the
    // right-bottom of the work area.
    // TODO(mukai): allow to specify the placement policy from outside of this
    // class. The policy should be specified from preference on Windows, or
    // the launcher alignment on ChromeOS.
    if (widget) {
      gfx::Rect bounds(widget->GetWindowBoundsInScreen());
      bounds.set_origin(gfx::Point(left, bottom - bounds.height()));
      widget->SetBounds(bounds);
      if (!widget->IsVisible())
        widget->Show();
    }

    bottom -= view_height + kMarginBetweenItems;
  }

  for (std::set<std::string>::const_iterator iter = old_toast_ids.begin();
       iter != old_toast_ids.end(); ++iter) {
    ToastContainer::iterator toast_iter = toasts_.find(*iter);
    DCHECK(toast_iter != toasts_.end());
    views::Widget* widget = toast_iter->second->GetWidget();
    widget->RemoveObserver(this);
    widget->Close();
    toasts_.erase(toast_iter);
  }
}

void MessagePopupCollection::OnMouseEntered() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->SuspendTimer();
  }
}

void MessagePopupCollection::OnMouseExited() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->RestartTimer();
  }
}

void MessagePopupCollection::CloseAllWidgets() {
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    iter->second->SuspendTimer();
    views::Widget* widget = iter->second->GetWidget();
    widget->RemoveObserver(this);
    widget->Close();
  }
  toasts_.clear();
}

void MessagePopupCollection::OnWidgetDestroying(views::Widget* widget) {
  widget->RemoveObserver(this);
  for (ToastContainer::iterator iter = toasts_.begin();
       iter != toasts_.end(); ++iter) {
    if (iter->second->GetWidget() == widget) {
      message_center_->notification_list()->MarkSinglePopupAsShown(
          iter->first, false);
      toasts_.erase(iter);
      break;
    }
  }
  UpdatePopups();
}

}  // namespace message_center
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/history/top_sites_extension_api.h"

#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"

GetTopSitesFunction::GetTopSitesFunction() {
}

GetTopSitesFunction::~GetTopSitesFunction() {
}

bool GetTopSitesFunction::RunImpl() {
  history::TopSites* ts = profile()->GetTopSites();
  if (!ts)
    return false;

  ts->GetMostVisitedURLs(
      &topsites_consumer_,
      base::Bind(&GetTopSitesFunction::OnMostVisitedURLsAvailable, this));
  return true;
}

void GetTopSitesFunction::OnMostVisitedURLsAvailable(
    const history::MostVisitedURLList& data) {
  // Code is a direct rip from most_visited_handler.cc TODO(estade): unfork.
  scoped_ptr<base::ListValue> pages_value(new ListValue);
  for (size_t i = 0; i < data.size(); i++) {
    const history::MostVisitedURL& url = data[i];
    DictionaryValue* page_value = new DictionaryValue();
    if (url.url.is_empty()) {
      page_value->SetBoolean("filler", true);
      pages_value->Append(page_value);
      continue;
    }

    NewTabUI::SetURLTitleAndDirection(page_value,
                                      url.title,
                                      url.url);
    if (!url.favicon_url.is_empty())
      page_value->SetString("faviconUrl", url.favicon_url.spec());

    // In MostVisitedHandler, there's special code here for the
    // prepopulated thumbnails, but we can't replicate it here conveniently.
    // TODO(estade) Do something else instead.

    history::TopSites* ts = profile()->GetTopSites();
    if (ts && ts->IsURLPinned(url.url))
      page_value->SetBoolean("pinned", true);
    pages_value->Append(page_value);
  }
  // End copied code. ----------------------------------------------------------

  result_.reset(pages_value.release());
  SendResponse(true);
}
<commit_msg>fix top sites compile breakage from patch conflict<commit_after>// Copyright (c) 2011 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/history/top_sites_extension_api.h"

#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"

GetTopSitesFunction::GetTopSitesFunction() {
}

GetTopSitesFunction::~GetTopSitesFunction() {
}

bool GetTopSitesFunction::RunImpl() {
  history::TopSites* ts = profile()->GetTopSites();
  if (!ts)
    return false;

  ts->GetMostVisitedURLs(
      &topsites_consumer_,
      base::Bind(&GetTopSitesFunction::OnMostVisitedURLsAvailable, this));
  return true;
}

void GetTopSitesFunction::OnMostVisitedURLsAvailable(
    const history::MostVisitedURLList& data) {
  // Code is a direct rip from most_visited_handler.cc TODO(estade): unfork.
  scoped_ptr<base::ListValue> pages_value(new ListValue);
  for (size_t i = 0; i < data.size(); i++) {
    const history::MostVisitedURL& url = data[i];
    DictionaryValue* page_value = new DictionaryValue();
    if (url.url.is_empty()) {
      page_value->SetBoolean("filler", true);
      pages_value->Append(page_value);
      continue;
    }

    NewTabUI::SetURLTitleAndDirection(page_value,
                                      url.title,
                                      url.url);

    pages_value->Append(page_value);
  }
  // End copied code. ----------------------------------------------------------

  result_.reset(pages_value.release());
  SendResponse(true);
}
<|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/prerender/prerender_field_trial.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/predictors/autocomplete_action_predictor.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"

using base::FieldTrial;
using base::FieldTrialList;

namespace prerender {

namespace {

const char kOmniboxTrialName[] = "PrerenderFromOmnibox";
int g_omnibox_trial_default_group_number = kint32min;

const char kSpeculativePrefetchingLearningTrialName[] =
    "SpeculativePrefetchingLearning";
int g_speculative_prefetching_learning_default_group_number = kint32min;

void SetupPrefetchFieldTrial() {
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    return;
  }

  const FieldTrial::Probability divisor = 1000;
  const FieldTrial::Probability prefetch_probability = 500;
  scoped_refptr<FieldTrial> trial(
      FieldTrialList::FactoryGetFieldTrial(
          "Prefetch", divisor, "ContentPrefetchPrefetchOff",
          2013, 6, 30, NULL));
  const int kPrefetchOnGroup = trial->AppendGroup("ContentPrefetchPrefetchOn",
                                                  prefetch_probability);
  PrerenderManager::SetIsPrefetchEnabled(trial->group() == kPrefetchOnGroup);
}

void SetupPrerenderFieldTrial() {
  const FieldTrial::Probability divisor = 1000;

  FieldTrial::Probability prerender_enabled_probability;
  FieldTrial::Probability control_probability;
  FieldTrial::Probability experiment_5min_ttl_probability;
  FieldTrial::Probability experiment_no_use_probability;

  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    // Use very conservatives and stable settings in beta and stable.
    const FieldTrial::Probability release_prerender_enabled_probability = 980;
    const FieldTrial::Probability release_control_probability = 10;
    const FieldTrial::Probability release_experiment_5min_ttl_probability = 10;
    const FieldTrial::Probability release_experiment_no_use_probability = 0;
    COMPILE_ASSERT(
        release_prerender_enabled_probability + release_control_probability +
        release_experiment_5min_ttl_probability +
        release_experiment_no_use_probability == divisor,
        release_experiment_probabilities_must_equal_divisor);

    prerender_enabled_probability = release_prerender_enabled_probability;
    control_probability = release_experiment_5min_ttl_probability;
    experiment_5min_ttl_probability = release_control_probability;
    experiment_no_use_probability = release_experiment_no_use_probability;
  } else {
    // In testing channels, use more experiments and a larger control group to
    // improve quality of data.
    const FieldTrial::Probability dev_prerender_enabled_probability = 333;
    const FieldTrial::Probability dev_control_probability = 333;
    const FieldTrial::Probability dev_experiment_5min_ttl_probability = 167;
    const FieldTrial::Probability dev_experiment_no_use_probability = 167;
    COMPILE_ASSERT(dev_prerender_enabled_probability + dev_control_probability +
                   dev_experiment_5min_ttl_probability +
                   dev_experiment_no_use_probability == divisor,
                   dev_experiment_probabilities_must_equal_divisor);

    prerender_enabled_probability = dev_prerender_enabled_probability;
    control_probability = dev_experiment_5min_ttl_probability;
    experiment_5min_ttl_probability = dev_control_probability;
    experiment_no_use_probability = dev_experiment_no_use_probability;
  }

  int prerender_enabled_group = -1;
  scoped_refptr<FieldTrial> trial(
      FieldTrialList::FactoryGetFieldTrial(
          "Prerender", divisor, "PrerenderEnabled",
          2013, 6, 30, &prerender_enabled_group));
  const int control_group =
      trial->AppendGroup("PrerenderControl",
                         control_probability);
  const int experiment_5_min_TTL_group =
      trial->AppendGroup("Prerender5minTTL",
                         experiment_5min_ttl_probability);
  const int experiment_no_use_group =
      trial->AppendGroup("PrerenderNoUse",
                         experiment_no_use_probability);

  const int trial_group = trial->group();
  if (trial_group == prerender_enabled_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
  } else if (trial_group == control_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
  } else if (trial_group == experiment_5_min_TTL_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP);
  } else if (trial_group == experiment_no_use_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
  } else {
    NOTREACHED();
  }
}

}  // end namespace

void ConfigureOmniboxPrerender();
void ConfigureSpeculativePrefetching();

void ConfigurePrefetchAndPrerender(const CommandLine& command_line) {
  enum PrerenderOption {
    PRERENDER_OPTION_AUTO,
    PRERENDER_OPTION_DISABLED,
    PRERENDER_OPTION_ENABLED,
    PRERENDER_OPTION_PREFETCH_ONLY,
  };

  PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
  if (command_line.HasSwitch(switches::kPrerenderMode)) {
    const std::string switch_value =
        command_line.GetSwitchValueASCII(switches::kPrerenderMode);

    if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
      prerender_option = PRERENDER_OPTION_AUTO;
    } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
      prerender_option = PRERENDER_OPTION_DISABLED;
    } else if (switch_value.empty() ||
               switch_value == switches::kPrerenderModeSwitchValueEnabled) {
      // The empty string means the option was provided with no value, and that
      // means enable.
      prerender_option = PRERENDER_OPTION_ENABLED;
    } else if (switch_value ==
               switches::kPrerenderModeSwitchValuePrefetchOnly) {
      prerender_option = PRERENDER_OPTION_PREFETCH_ONLY;
    } else {
      prerender_option = PRERENDER_OPTION_DISABLED;
      LOG(ERROR) << "Invalid --prerender option received on command line: "
                 << switch_value;
      LOG(ERROR) << "Disabling prerendering!";
    }
  }

  switch (prerender_option) {
    case PRERENDER_OPTION_AUTO:
      SetupPrefetchFieldTrial();
      SetupPrerenderFieldTrial();
      break;
    case PRERENDER_OPTION_DISABLED:
      PrerenderManager::SetIsPrefetchEnabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    case PRERENDER_OPTION_ENABLED:
      PrerenderManager::SetIsPrefetchEnabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
      break;
    case PRERENDER_OPTION_PREFETCH_ONLY:
      PrerenderManager::SetIsPrefetchEnabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    default:
      NOTREACHED();
  }

  UMA_HISTOGRAM_ENUMERATION("Prerender.Sessions",
                            PrerenderManager::GetMode(),
                            PrerenderManager::PRERENDER_MODE_MAX);

  ConfigureOmniboxPrerender();
  ConfigureSpeculativePrefetching();
}

void ConfigureOmniboxPrerender() {
  // Field trial to see if we're enabled.
  const FieldTrial::Probability kDivisor = 100;

  FieldTrial::Probability kDisabledProbability = 10;
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    kDisabledProbability = 1;
  }
  scoped_refptr<FieldTrial> omnibox_prerender_trial(
      FieldTrialList::FactoryGetFieldTrial(
          kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled",
          2012, 12, 30, &g_omnibox_trial_default_group_number));
  omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled",
                                       kDisabledProbability);
}

bool IsOmniboxEnabled(Profile* profile) {
  if (!profile)
    return false;

  if (!PrerenderManager::IsPrerenderingPossible())
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kPrerenderFromOmnibox)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kPrerenderFromOmnibox);

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
      return true;

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
      return false;

    DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto);
  }

  const int group = FieldTrialList::FindValue(kOmniboxTrialName);
  return group == FieldTrial::kNotFinalized ||
         group == g_omnibox_trial_default_group_number;
}

void ConfigureSpeculativePrefetching() {
  // Field trial to see if we're enabled.
  const FieldTrial::Probability kDivisor = 100;

  FieldTrial::Probability kDisabledProbability = 99;
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    kDisabledProbability = 100;
  }
  scoped_refptr<FieldTrial> speculative_prefetching_learning_trial(
      FieldTrialList::FactoryGetFieldTrial(
          kSpeculativePrefetchingLearningTrialName,
          kDivisor,
          "SpeculativePrefetchingLearningEnabled",
          2012, 12, 30,
          &g_speculative_prefetching_learning_default_group_number));
  speculative_prefetching_learning_trial->AppendGroup(
      "SpeculativePrefetchingDisabled",
      kDisabledProbability);
}

bool IsSpeculativeResourcePrefetchingLearningEnabled(Profile* profile) {
  if (!profile)
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kSpeculativeResourcePrefetching)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kSpeculativeResourcePrefetching);

    if (switch_value == switches::kSpeculativeResourcePrefetchingLearning)
      return true;
  }

  const int group = FieldTrialList::FindValue(
      kSpeculativePrefetchingLearningTrialName);
  return group == g_speculative_prefetching_learning_default_group_number;
}

}  // namespace prerender
<commit_msg>Revert 148639 - Clean up Prerender field trials.<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/prerender/prerender_field_trial.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/predictors/autocomplete_action_predictor.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"

namespace prerender {

namespace {

const char kOmniboxTrialName[] = "PrerenderFromOmnibox";
int g_omnibox_trial_default_group_number = kint32min;

const char kSpeculativePrefetchingLearningTrialName[] =
    "SpeculativePrefetchingLearning";
int g_speculative_prefetching_learning_default_group_number = kint32min;

void SetupPrefetchFieldTrial() {
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    return;
  }

  const base::FieldTrial::Probability divisor = 1000;
  const base::FieldTrial::Probability prefetch_probability = 500;
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          "Prefetch", divisor, "ContentPrefetchPrefetchOff",
          2013, 6, 30, NULL));
  const int kPrefetchOnGroup = trial->AppendGroup("ContentPrefetchPrefetchOn",
                                                  prefetch_probability);
  PrerenderManager::SetIsPrefetchEnabled(trial->group() == kPrefetchOnGroup);
}

void SetupPrerenderFieldTrial() {
  base::FieldTrial::Probability divisor = 1000;

  base::FieldTrial::Probability exp1_probability = 166;
  base::FieldTrial::Probability exp1_5min_ttl_probability = 83;
  base::FieldTrial::Probability control1_probability = 166;
  base::FieldTrial::Probability no_use1_probability = 83;

  base::FieldTrial::Probability exp2_probability = 167;
  base::FieldTrial::Probability exp2_5min_ttl_probability = 84;
  base::FieldTrial::Probability control2_probability = 167;
  base::FieldTrial::Probability no_use2_probability = 84;

  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    exp1_probability = 490;
    exp1_5min_ttl_probability = 5;
    control1_probability = 5;
    no_use1_probability = 0;
    exp2_probability = 490;
    exp2_5min_ttl_probability = 5;
    control2_probability = 5;
    no_use2_probability = 0;
  }
  CHECK_EQ(divisor, exp1_probability + exp1_5min_ttl_probability +
           control1_probability + no_use1_probability + exp2_probability +
           exp2_5min_ttl_probability + control2_probability +
           no_use2_probability);
  int experiment_1_group = -1;
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          "Prerender", divisor, "ContentPrefetchPrerender1",
          2013, 6, 30, &experiment_1_group));

  const int experiment_15_min_TTL_group =
      trial->AppendGroup("ContentPrefetchPrerenderExp5minTTL1",
                         exp1_5min_ttl_probability);
  const int control_1_group =
      trial->AppendGroup("ContentPrefetchPrerenderControl1",
                         control1_probability);
  const int no_use_1_group =
      trial->AppendGroup("ContentPrefetchPrerenderNoUse1",
                         no_use1_probability);
  const int experiment_2_group =
      trial->AppendGroup("ContentPrefetchPrerender2",
                         exp2_probability);
  const int experiment_25_min_TTL_group =
      trial->AppendGroup("ContentPrefetchPrerenderExp5minTTL2",
                         exp2_5min_ttl_probability);
  const int control_2_group =
      trial->AppendGroup("ContentPrefetchPrerenderControl2",
                         control2_probability);
  const int no_use_2_group =
      trial->AppendGroup("ContentPrefetchPrerenderNoUse2",
                         no_use2_probability);
  const int trial_group = trial->group();
  if (trial_group == experiment_1_group ||
      trial_group == experiment_2_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
  } else if (trial_group == experiment_15_min_TTL_group ||
             trial_group == experiment_25_min_TTL_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP);
  } else if (trial_group == control_1_group ||
             trial_group == control_2_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
  } else if (trial_group == no_use_1_group ||
             trial_group == no_use_2_group) {
    PrerenderManager::SetMode(
        PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
  } else {
    NOTREACHED();
  }
}

}  // end namespace

void ConfigureOmniboxPrerender();
void ConfigureSpeculativePrefetching();

void ConfigurePrefetchAndPrerender(const CommandLine& command_line) {
  enum PrerenderOption {
    PRERENDER_OPTION_AUTO,
    PRERENDER_OPTION_DISABLED,
    PRERENDER_OPTION_ENABLED,
    PRERENDER_OPTION_PREFETCH_ONLY,
  };

  PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
  if (command_line.HasSwitch(switches::kPrerenderMode)) {
    const std::string switch_value =
        command_line.GetSwitchValueASCII(switches::kPrerenderMode);

    if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
      prerender_option = PRERENDER_OPTION_AUTO;
    } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
      prerender_option = PRERENDER_OPTION_DISABLED;
    } else if (switch_value.empty() ||
               switch_value == switches::kPrerenderModeSwitchValueEnabled) {
      // The empty string means the option was provided with no value, and that
      // means enable.
      prerender_option = PRERENDER_OPTION_ENABLED;
    } else if (switch_value ==
               switches::kPrerenderModeSwitchValuePrefetchOnly) {
      prerender_option = PRERENDER_OPTION_PREFETCH_ONLY;
    } else {
      prerender_option = PRERENDER_OPTION_DISABLED;
      LOG(ERROR) << "Invalid --prerender option received on command line: "
                 << switch_value;
      LOG(ERROR) << "Disabling prerendering!";
    }
  }

  switch (prerender_option) {
    case PRERENDER_OPTION_AUTO:
      SetupPrefetchFieldTrial();
      SetupPrerenderFieldTrial();
      break;
    case PRERENDER_OPTION_DISABLED:
      PrerenderManager::SetIsPrefetchEnabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    case PRERENDER_OPTION_ENABLED:
      PrerenderManager::SetIsPrefetchEnabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
      break;
    case PRERENDER_OPTION_PREFETCH_ONLY:
      PrerenderManager::SetIsPrefetchEnabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    default:
      NOTREACHED();
  }

  UMA_HISTOGRAM_ENUMERATION("Prerender.Sessions",
                            PrerenderManager::GetMode(),
                            PrerenderManager::PRERENDER_MODE_MAX);

  ConfigureOmniboxPrerender();
  ConfigureSpeculativePrefetching();
}

void ConfigureOmniboxPrerender() {
  // Field trial to see if we're enabled.
  const base::FieldTrial::Probability kDivisor = 100;

  base::FieldTrial::Probability kDisabledProbability = 10;
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    kDisabledProbability = 1;
  }
  scoped_refptr<base::FieldTrial> omnibox_prerender_trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled",
          2012, 12, 30, &g_omnibox_trial_default_group_number));
  omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled",
                                       kDisabledProbability);
}

bool IsOmniboxEnabled(Profile* profile) {
  if (!profile)
    return false;

  if (!PrerenderManager::IsPrerenderingPossible())
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kPrerenderFromOmnibox)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kPrerenderFromOmnibox);

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
      return true;

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
      return false;

    DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto);
  }

  const int group = base::FieldTrialList::FindValue(kOmniboxTrialName);
  return group == base::FieldTrial::kNotFinalized ||
         group == g_omnibox_trial_default_group_number;
}

void ConfigureSpeculativePrefetching() {
  // Field trial to see if we're enabled.
  const base::FieldTrial::Probability kDivisor = 100;

  base::FieldTrial::Probability kDisabledProbability = 99;
  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
  if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
      channel == chrome::VersionInfo::CHANNEL_BETA) {
    kDisabledProbability = 100;
  }
  scoped_refptr<base::FieldTrial> speculative_prefetching_learning_trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          kSpeculativePrefetchingLearningTrialName,
          kDivisor,
          "SpeculativePrefetchingLearningEnabled",
          2012, 12, 30,
          &g_speculative_prefetching_learning_default_group_number));
  speculative_prefetching_learning_trial->AppendGroup(
      "SpeculativePrefetchingDisabled",
      kDisabledProbability);
}

bool IsSpeculativeResourcePrefetchingLearningEnabled(Profile* profile) {
  if (!profile)
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kSpeculativeResourcePrefetching)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kSpeculativeResourcePrefetching);

    if (switch_value == switches::kSpeculativeResourcePrefetchingLearning)
      return true;
  }

  const int group = base::FieldTrialList::FindValue(
      kSpeculativePrefetchingLearningTrialName);
  return group == g_speculative_prefetching_learning_default_group_number;
}

}  // namespace prerender
<|endoftext|>