<commit_before>// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

#include <util/strencodings.h>
#include <util/system.h>

#include <memory>

static const char *DEFAULT_BENCH_FILTER = ".*";

static void SetupBenchArgs(ArgsManager &argsman) {
    SetupHelpOptions(argsman);

    argsman.AddArg("-list", "List benchmarks without executing them",
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-filter=<regex>",
                   strprintf("Regular expression filter to select benchmark by "
                             "name (default: %s)",
                             DEFAULT_BENCH_FILTER),
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-asymptote=n1,n2,n3,...",
                   strprintf("Test asymptotic growth of the runtime of an "
                             "algorithm, if supported by the benchmark"),
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg(
        "-output_csv=<output.csv>",
        "Generate CSV file with the most important benchmark results.",
        ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-output_json=<output.json>",
                   "Generate JSON file with all benchmark results.",
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
}

// parses a comma separated list like "10,20,30,50"
static std::vector<double> parseAsymptote(const std::string &str) {
    std::stringstream ss(str);
    std::vector<double> numbers;
    double d;
    char c;
    while (ss >> d) {
        numbers.push_back(d);
        ss >> c;
    }
    return numbers;
}

int main(int argc, char **argv) {
    ArgsManager argsman;
    SetupBenchArgs(argsman);
    std::string error;
    if (!argsman.ParseParameters(argc, argv, error)) {
        tfm::format(std::cerr, "Error parsing command line arguments: %s\n",
                    error);
        return EXIT_FAILURE;
    }

    if (HelpRequested(argsman)) {
        std::cout << argsman.GetHelpMessage();
        return EXIT_SUCCESS;
    }

    benchmark::Args args;
    args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
    args.is_list_only = argsman.GetBoolArg("-list", false);
    args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
    args.output_csv = argsman.GetArg("-output_csv", "");
    args.output_json = argsman.GetArg("-output_json", "");

    benchmark::BenchRunner::RunAll(args);

    return EXIT_SUCCESS;
}
<commit_msg>Call SHA256AutoDetect in benchmark setup<commit_after>// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

#include <crypto/sha256.h>
#include <util/strencodings.h>
#include <util/system.h>

#include <memory>

static const char *DEFAULT_BENCH_FILTER = ".*";

static void SetupBenchArgs(ArgsManager &argsman) {
    SetupHelpOptions(argsman);

    argsman.AddArg("-list", "List benchmarks without executing them",
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-filter=<regex>",
                   strprintf("Regular expression filter to select benchmark by "
                             "name (default: %s)",
                             DEFAULT_BENCH_FILTER),
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-asymptote=n1,n2,n3,...",
                   strprintf("Test asymptotic growth of the runtime of an "
                             "algorithm, if supported by the benchmark"),
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg(
        "-output_csv=<output.csv>",
        "Generate CSV file with the most important benchmark results.",
        ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    argsman.AddArg("-output_json=<output.json>",
                   "Generate JSON file with all benchmark results.",
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
}

// parses a comma separated list like "10,20,30,50"
static std::vector<double> parseAsymptote(const std::string &str) {
    std::stringstream ss(str);
    std::vector<double> numbers;
    double d;
    char c;
    while (ss >> d) {
        numbers.push_back(d);
        ss >> c;
    }
    return numbers;
}

int main(int argc, char **argv) {
    ArgsManager argsman;
    SetupBenchArgs(argsman);
    SHA256AutoDetect();
    std::string error;
    if (!argsman.ParseParameters(argc, argv, error)) {
        tfm::format(std::cerr, "Error parsing command line arguments: %s\n",
                    error);
        return EXIT_FAILURE;
    }

    if (HelpRequested(argsman)) {
        std::cout << argsman.GetHelpMessage();
        return EXIT_SUCCESS;
    }

    benchmark::Args args;
    args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
    args.is_list_only = argsman.GetBoolArg("-list", false);
    args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
    args.output_csv = argsman.GetArg("-output_csv", "");
    args.output_json = argsman.GetArg("-output_json", "");

    benchmark::BenchRunner::RunAll(args);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

#include <sys/types.h>
#include <sys/stat.h>

#if defined(_WIN32)
#  include <shlobj.h>
#  include <direct.h>
#else
#  include <pwd.h>
#  include <dirent.h>
#endif /* defined(_WIN32) */

#include "clientConfig.h"

#include "version.h"
#include "StateDatabase.h"
#include "KeyManager.h"
#include "TextUtils.h"
#include "DirectoryNames.h"
#include "ErrorHandler.h"

std::vector<std::string> configQualityValues;
std::vector<std::string> configViewValues;

void initConfigData ( void )
{
	configQualityValues.push_back(std::string("low"));
	configQualityValues.push_back(std::string("medium"));
	configQualityValues.push_back(std::string("high"));
	configQualityValues.push_back(std::string("experimental"));

	configViewValues.push_back(std::string("normal"));
	configViewValues.push_back(std::string("stereo"));
	configViewValues.push_back(std::string("stacked"));
	configViewValues.push_back(std::string("three"));
	configViewValues.push_back(std::string("anaglyph"));
	configViewValues.push_back(std::string("interlaced"));
}

std::string	getOldConfigFileName(void)
{
#if !defined(_WIN32)

	std::string name = getConfigDirName("2.0");
	name += "config.cfg";

	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}

	return name;

#elif defined(_WIN32) /* !defined(_WIN32) */

	std::string name("C:");
	char dir[MAX_PATH];
	ITEMIDLIST* idl;
	if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL , &idl))) {
		if (SHGetPathFromIDList(idl, dir)) {
			struct stat statbuf;
			if (stat(dir, &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) != 0)
				name = dir;
		}

		IMalloc* shalloc;
		if (SUCCEEDED(SHGetMalloc(&shalloc))) {
			shalloc->Free(idl);
			shalloc->Release();
		}
	}

	name += "\\My BZFlag Files\\2.0\\config.cfg";
	return name;

#endif /* !defined(_WIN32) */
}

#if !defined(_WIN32)		// who uses this sucker any more?
static std::string	getReallyOldConfigFileName()
{
	std::string name = getConfigDirName();
	name += "config";
	return name;
}
#endif

std::string getCurrentConfigFileName(void)
{
	std::string configFile = BZ_CONFIG_FILE_NAME;

	std::string name = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	name += configFile;

#if !defined(_WIN32)
	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}
#endif
	return name;
}

#if !defined(_WIN32)
static void copyConfigFile(const char *oldConfigName, std::string configName) {

  FILE *fp = fopen(oldConfigName, "rb");
  if (!fp)
    return;

  // there is an old config so lets copy it to the new dir and let the
  // update take care of it.
  mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);
  FILE *newFile = fopen(configName.c_str(),"wb");
  if (!newFile)
    return;

  fseek(fp, 0, SEEK_END);
  const int len = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  unsigned char *temp = (unsigned char *)malloc(len);
  if (temp == NULL) {
    printError("Unsufficient Memory");
    fclose(fp);
    return;
  }

  size_t items_read = fread(temp, len, 1, fp);
  fclose(fp);
  if (items_read != 1)
    printError("Old config file is not readable");

  size_t items_written = fwrite(temp, len, 1, newFile);
  fclose(newFile);
  if (items_written != 1)
    printError("New config file is not writable");

  free (temp);
}
#endif

// this function will look for the config, if it's not there,
// it will TRY and find an old one and copy it
// so that the update function can upgrade it to the current version
// the assumption is that there is a unique config per version
void findConfigFile(void)
{
	// look for the current file
	std::string configName = getCurrentConfigFileName();
	FILE *fp = fopen(configName.c_str(), "rb");
	if (fp) {
		// we found the current file, nothing to do, just return
		fclose(fp);
		return;
	}

	// try and find the old file
	std::string oldConfigName = getOldConfigFileName();
#if defined(_WIN32)
	fp = fopen(oldConfigName.c_str(), "rb");
	if (fp) {
	  // there is an old config so lets copy it to the new dir and
	  // let the update take care of it.
	  fclose(fp);
	  // make the dir if we need to
	  std::string configDir = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	  mkdir(configDir.c_str());
	  // copy the old config to the new dir location with the new name
	  CopyFile(oldConfigName.c_str(), configName.c_str(),true);
	}
#else	// the other OSs should do what they need to do
	copyConfigFile(oldConfigName.c_str(), configName);
#endif

	// try and find the REALLY old file
	// who uses this sucker any more?
#if !defined(_WIN32)
	std::string realyOldConfigName = getReallyOldConfigFileName();
	// apparently only linux needs this so do the magic
	copyConfigFile(realyOldConfigName.c_str(), configName);
#endif
}

void updateConfigFile(void)
{
	int		configVersion = 0;
	if (BZDB.isSet("config_version"))
		configVersion = (int)BZDB.eval("config_version");

	switch (configVersion) {
  case 0: // 1.10-1.12
	  // update from old unversioned config
	  // roaming fixes - remove keys bound to "roam translate *" and "roam rotate *"
	  KEYMGR.unbindCommand("roam translate left");
	  KEYMGR.unbindCommand("roam translate right");
	  KEYMGR.unbindCommand("roam translate up");
	  KEYMGR.unbindCommand("roam translate down");
	  KEYMGR.unbindCommand("roam translate forward");
	  KEYMGR.unbindCommand("roam translate backward");
	  KEYMGR.unbindCommand("roam rotate left");
	  KEYMGR.unbindCommand("roam rotate right");
	  KEYMGR.unbindCommand("roam rotate up");
	  KEYMGR.unbindCommand("roam rotate down");
	  KEYMGR.unbindCommand("roam rotate stop");

	  // add new default keybindings if there's no conflict

	  // iconify
	  BzfKeyEvent key;
	  if (KEYMGR.stringToKeyEvent("F4", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "iconify");
	  // toggle console & radar
	  if (KEYMGR.stringToKeyEvent("Q", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleRadar");
	  if (KEYMGR.stringToKeyEvent("W", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleConsole");
	  // controlpanel tabs - all or nothing
	  if (KEYMGR.stringToKeyEvent("Shift+F1", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F2", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F3", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F4", key)
		  && (KEYMGR.get(key, true) == "")) {
			  KEYMGR.stringToKeyEvent("Shift+F1", key);
			  KEYMGR.bind(key, true, "messagepanel all");
			  KEYMGR.stringToKeyEvent("Shift+F2", key);
			  KEYMGR.bind(key, true, "messagepanel chat");
			  KEYMGR.stringToKeyEvent("Shift+F3", key);
			  KEYMGR.bind(key, true, "messagepanel server");
			  KEYMGR.stringToKeyEvent("Shift+F4", key);
			  KEYMGR.bind(key, true, "messagepanel misc");
		  }

		  // TODO - any other breaking changes from 1.10 to 2.0

  case 1: // 1.11.20
	  if (KEYMGR.stringToKeyEvent("Tab", key)
		  && (KEYMGR.get(key, false) == ""))
		  KEYMGR.bind(key, false, "jump");

  case 2: // 2.0
	  if (KEYMGR.stringToKeyEvent("7", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "addhunt");

  case 3: // Upgrade from 2.0.x to 2.4.x

    // Convert from email to motto

    // If the email is set, see if we should convert it
    if (BZDB.isSet("email")) {
      std::string email = BZDB.get("email");
      // If the email is set and does not contain an @ sign, move it to motto
      if (!email.empty() && email.find('@') == std::string::npos) {
	BZDB.set("motto", email);
      }
      BZDB.unset("email");	// discard email string from before version 2.4
    }

    if (BZDB.isSet("emailDispLen")) {
      BZDB.set("mottoDispLen", BZDB.get("emailDispLen"));
      BZDB.unset("emailDispLen");	// discard setting from before version 2.4
    }

    if (BZDB.isSet("hideEmails")) {
      BZDB.setBool("hideMottos", BZDB.isTrue("hideEmails"));
      BZDB.unset("hideEmails");	// discard setting from before version 2.4
    }

    // Get rid of geometry and lastScreenshot settings
    BZDB.unset("geometry");
    BZDB.unset("lastScreenshot");

    // Turn off dithering (since none of our automatic performance checks turn it on anymore)
    BZDB.setBool("dither", false);

  case 4: // Upgrade 2.4.0 to 2.4.1
    BZDB.unset("displayZoom");		// removed in r22109
    BZDB.unset("radarShotLineType");	// existed only in r22117
    break;

  default: // hm, we don't know about this one...
	  printError(TextUtils::format("Config file is tagged version \"%d\", "
		  "which was not expected (too new perhaps). "
		  "Trying to load anyhow.", configVersion));
	  break;
	}

	// set us as the updated version
	configVersion = BZ_CONFIG_FILE_VERSION;
	BZDB.setInt("config_version", configVersion);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Avoid resource (file stream) leak when handling errors.<commit_after>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

#include <sys/types.h>
#include <sys/stat.h>

#if defined(_WIN32)
#  include <shlobj.h>
#  include <direct.h>
#else
#  include <pwd.h>
#  include <dirent.h>
#endif /* defined(_WIN32) */

#include "clientConfig.h"

#include "version.h"
#include "StateDatabase.h"
#include "KeyManager.h"
#include "TextUtils.h"
#include "DirectoryNames.h"
#include "ErrorHandler.h"

std::vector<std::string> configQualityValues;
std::vector<std::string> configViewValues;

void initConfigData ( void )
{
	configQualityValues.push_back(std::string("low"));
	configQualityValues.push_back(std::string("medium"));
	configQualityValues.push_back(std::string("high"));
	configQualityValues.push_back(std::string("experimental"));

	configViewValues.push_back(std::string("normal"));
	configViewValues.push_back(std::string("stereo"));
	configViewValues.push_back(std::string("stacked"));
	configViewValues.push_back(std::string("three"));
	configViewValues.push_back(std::string("anaglyph"));
	configViewValues.push_back(std::string("interlaced"));
}

std::string	getOldConfigFileName(void)
{
#if !defined(_WIN32)

	std::string name = getConfigDirName("2.0");
	name += "config.cfg";

	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}

	return name;

#elif defined(_WIN32) /* !defined(_WIN32) */

	std::string name("C:");
	char dir[MAX_PATH];
	ITEMIDLIST* idl;
	if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL , &idl))) {
		if (SHGetPathFromIDList(idl, dir)) {
			struct stat statbuf;
			if (stat(dir, &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) != 0)
				name = dir;
		}

		IMalloc* shalloc;
		if (SUCCEEDED(SHGetMalloc(&shalloc))) {
			shalloc->Free(idl);
			shalloc->Release();
		}
	}

	name += "\\My BZFlag Files\\2.0\\config.cfg";
	return name;

#endif /* !defined(_WIN32) */
}

#if !defined(_WIN32)		// who uses this sucker any more?
static std::string	getReallyOldConfigFileName()
{
	std::string name = getConfigDirName();
	name += "config";
	return name;
}
#endif

std::string getCurrentConfigFileName(void)
{
	std::string configFile = BZ_CONFIG_FILE_NAME;

	std::string name = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	name += configFile;

#if !defined(_WIN32)
	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}
#endif
	return name;
}

#if !defined(_WIN32)
static void copyConfigFile(const char *oldConfigName, std::string configName) {

  FILE *fp = fopen(oldConfigName, "rb");
  if (!fp)
    return;

  // there is an old config so lets copy it to the new dir and let the
  // update take care of it.
  mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);
  FILE *newFile = fopen(configName.c_str(),"wb");
  if (!newFile) {
    fclose(fp);
    return;
  }

  fseek(fp, 0, SEEK_END);
  const int len = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  unsigned char *temp = (unsigned char *)malloc(len);
  if (temp == NULL) {
    printError("Unsufficient Memory");
    fclose(fp);
    fclose(newFile);
    return;
  }

  size_t items_read = fread(temp, len, 1, fp);
  fclose(fp);
  if (items_read != 1)
    printError("Old config file is not readable");

  size_t items_written = fwrite(temp, len, 1, newFile);
  fclose(newFile);
  if (items_written != 1)
    printError("New config file is not writable");

  free (temp);
}
#endif

// this function will look for the config, if it's not there,
// it will TRY and find an old one and copy it
// so that the update function can upgrade it to the current version
// the assumption is that there is a unique config per version
void findConfigFile(void)
{
	// look for the current file
	std::string configName = getCurrentConfigFileName();
	FILE *fp = fopen(configName.c_str(), "rb");
	if (fp) {
		// we found the current file, nothing to do, just return
		fclose(fp);
		return;
	}

	// try and find the old file
	std::string oldConfigName = getOldConfigFileName();
#if defined(_WIN32)
	fp = fopen(oldConfigName.c_str(), "rb");
	if (fp) {
	  // there is an old config so lets copy it to the new dir and
	  // let the update take care of it.
	  fclose(fp);
	  // make the dir if we need to
	  std::string configDir = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	  mkdir(configDir.c_str());
	  // copy the old config to the new dir location with the new name
	  CopyFile(oldConfigName.c_str(), configName.c_str(),true);
	}
#else	// the other OSs should do what they need to do
	copyConfigFile(oldConfigName.c_str(), configName);
#endif

	// try and find the REALLY old file
	// who uses this sucker any more?
#if !defined(_WIN32)
	std::string realyOldConfigName = getReallyOldConfigFileName();
	// apparently only linux needs this so do the magic
	copyConfigFile(realyOldConfigName.c_str(), configName);
#endif
}

void updateConfigFile(void)
{
	int		configVersion = 0;
	if (BZDB.isSet("config_version"))
		configVersion = (int)BZDB.eval("config_version");

	switch (configVersion) {
  case 0: // 1.10-1.12
	  // update from old unversioned config
	  // roaming fixes - remove keys bound to "roam translate *" and "roam rotate *"
	  KEYMGR.unbindCommand("roam translate left");
	  KEYMGR.unbindCommand("roam translate right");
	  KEYMGR.unbindCommand("roam translate up");
	  KEYMGR.unbindCommand("roam translate down");
	  KEYMGR.unbindCommand("roam translate forward");
	  KEYMGR.unbindCommand("roam translate backward");
	  KEYMGR.unbindCommand("roam rotate left");
	  KEYMGR.unbindCommand("roam rotate right");
	  KEYMGR.unbindCommand("roam rotate up");
	  KEYMGR.unbindCommand("roam rotate down");
	  KEYMGR.unbindCommand("roam rotate stop");

	  // add new default keybindings if there's no conflict

	  // iconify
	  BzfKeyEvent key;
	  if (KEYMGR.stringToKeyEvent("F4", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "iconify");
	  // toggle console & radar
	  if (KEYMGR.stringToKeyEvent("Q", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleRadar");
	  if (KEYMGR.stringToKeyEvent("W", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleConsole");
	  // controlpanel tabs - all or nothing
	  if (KEYMGR.stringToKeyEvent("Shift+F1", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F2", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F3", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F4", key)
		  && (KEYMGR.get(key, true) == "")) {
			  KEYMGR.stringToKeyEvent("Shift+F1", key);
			  KEYMGR.bind(key, true, "messagepanel all");
			  KEYMGR.stringToKeyEvent("Shift+F2", key);
			  KEYMGR.bind(key, true, "messagepanel chat");
			  KEYMGR.stringToKeyEvent("Shift+F3", key);
			  KEYMGR.bind(key, true, "messagepanel server");
			  KEYMGR.stringToKeyEvent("Shift+F4", key);
			  KEYMGR.bind(key, true, "messagepanel misc");
		  }

		  // TODO - any other breaking changes from 1.10 to 2.0

  case 1: // 1.11.20
	  if (KEYMGR.stringToKeyEvent("Tab", key)
		  && (KEYMGR.get(key, false) == ""))
		  KEYMGR.bind(key, false, "jump");

  case 2: // 2.0
	  if (KEYMGR.stringToKeyEvent("7", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "addhunt");

  case 3: // Upgrade from 2.0.x to 2.4.x

    // Convert from email to motto

    // If the email is set, see if we should convert it
    if (BZDB.isSet("email")) {
      std::string email = BZDB.get("email");
      // If the email is set and does not contain an @ sign, move it to motto
      if (!email.empty() && email.find('@') == std::string::npos) {
	BZDB.set("motto", email);
      }
      BZDB.unset("email");	// discard email string from before version 2.4
    }

    if (BZDB.isSet("emailDispLen")) {
      BZDB.set("mottoDispLen", BZDB.get("emailDispLen"));
      BZDB.unset("emailDispLen");	// discard setting from before version 2.4
    }

    if (BZDB.isSet("hideEmails")) {
      BZDB.setBool("hideMottos", BZDB.isTrue("hideEmails"));
      BZDB.unset("hideEmails");	// discard setting from before version 2.4
    }

    // Get rid of geometry and lastScreenshot settings
    BZDB.unset("geometry");
    BZDB.unset("lastScreenshot");

    // Turn off dithering (since none of our automatic performance checks turn it on anymore)
    BZDB.setBool("dither", false);

  case 4: // Upgrade 2.4.0 to 2.4.1
    BZDB.unset("displayZoom");		// removed in r22109
    BZDB.unset("radarShotLineType");	// existed only in r22117
    break;

  default: // hm, we don't know about this one...
	  printError(TextUtils::format("Config file is tagged version \"%d\", "
		  "which was not expected (too new perhaps). "
		  "Trying to load anyhow.", configVersion));
	  break;
	}

	// set us as the updated version
	configVersion = BZ_CONFIG_FILE_VERSION;
	BZDB.setInt("config_version", configVersion);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// \brief Properties implementation.
//
// Created 2004/05/05
//
// Copyright 2008-2012 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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 <iostream>
#include <fstream>
#include <cstdlib>
#include "Properties.h"
#include "RequestParser.h"

namespace KFS
{

using std::string;
using std::istream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::endl;

inline static int
AsciiCharToLower(int c)
{
    return ((c >= 'A' && c <= 'Z') ? 'a' + (c - 'A') : c);
}

template<typename T> inline static void
removeLTSpaces(const string& str, string::size_type start,
    string::size_type end, T& outStr, bool asciiToLower = false)
{
    char const* const delims = " \t\r\n";

    if (start >= str.length()) {
        outStr.clear();
        return;
    }
    string::size_type const first = str.find_first_not_of(delims, start);
    if (end <= first || first == string::npos) {
        outStr.clear();
        return;
    }
    string::size_type const last = str.find_last_not_of(
        delims, end == string::npos ? string::npos : end - 1);
    if (asciiToLower) {
        outStr.clear();
        for (const char* p = str.data() + first,
                * e = str.data() +
                    (last == string::npos ? str.size() : last + 1);
                p < e;
                ++p) {
            outStr.Append(AsciiCharToLower(*p & 0xFF));
        }
        return;
    }
    outStr.Copy(str.c_str() + first,
        (last == string::npos ? str.size() : last + 1) - first);
}

/* static */ string
Properties::AsciiToLower(const string& str)
{
    string s(str);
    for (string::iterator i = s.begin(); i != s.end(); ++i) {
        const int c = AsciiCharToLower(*i & 0xFF);
        if (c != *i) {
            *i = c;
        }
    }
    return s;
}

inline Properties::iterator
Properties::find(const Properties::String& key) const
{
    return propmap.find(key);
}

Properties::Properties(int base)
    : intbase(base),
      propmap()
{
}

Properties::Properties(const Properties &p)
    : intbase(p.intbase),
      propmap(p.propmap)
{
}

Properties::~Properties()
{
}

int
Properties::loadProperties(
    const char* fileName,
    char        delimiter,
    bool        verbose /* = false */,
    bool        multiline /* =false */,
    bool        keysAsciiToLower /* = false */)
{
    ifstream input(fileName);
    if(! input.is_open()) {
        cerr <<  "Properties::loadProperties() failed to open the file:" <<
            fileName << endl;
        return(-1);
    }
    loadProperties(input, delimiter, verbose, multiline, keysAsciiToLower);
    input.close();
    return 0;
}

int
Properties::loadProperties(
    istream& ist,
    char     delimiter,
    bool     verbose,
    bool     multiline /* = false */,
    bool     keysAsciiToLower /* = false */)
{
    string line;
    String key;
    String val;
    if (ist) {
        line.reserve(512);
    }
    while (ist) {
        getline(ist, line); //read one line at a time
        if (line.empty() || line[0] == '#') {
            continue; // ignore comments
        }
        // find the delimiter
        string::size_type const pos = line.find(delimiter);
        if (pos == string::npos) {
            continue; // ignore if no delimiter is found
        }
        removeLTSpaces(line, 0, pos, key, keysAsciiToLower);
        removeLTSpaces(line, pos + 1, string::npos, val);
        if (multiline) {
            // allow properties to span across multiple lines
            propmap[key].Append(val);
        } else {
            propmap[key] = val;
        }
        if (verbose) {
            cout << "Loading key " << key  <<
                " with value " << propmap[key] << endl;
        }
    }
    return 0;
}

int
Properties::loadProperties(
    const char* buf,
    size_t      len,
    char        delimiter,
    ostream*    verbose /* = 0 */,
    bool        multiline /* = false */,
    bool        keysAsciiToLower /* = false */)
{
    PropertiesTokenizer tokenizer(buf, len);
    if (keysAsciiToLower) {
        String lkey;
        while (tokenizer.Next(delimiter)) {
            const PropertiesTokenizer::Token& key = tokenizer.GetKey();
            const PropertiesTokenizer::Token& val = tokenizer.GetValue();
            lkey.clear();
            for (const char* p = key.mPtr, * e = p + key.mLen; p < e; ++p) {
                lkey.Append(AsciiCharToLower(*p & 0xFF));
            }
            if (multiline) {
                propmap[lkey].Append(val.mPtr, val.mLen);
            } else {
                propmap[lkey].Copy(val.mPtr, val.mLen);
            }
            if (verbose) {
                (*verbose) << "Loading key ";
                verbose->write(key.mPtr, key.mLen);
                (*verbose) << " with value ";
                verbose->write(val.mPtr, val.mLen);
                (*verbose) << endl;
            }
        }
    } else {
        while (tokenizer.Next(delimiter)) {
            const PropertiesTokenizer::Token& key = tokenizer.GetKey();
            const PropertiesTokenizer::Token& val = tokenizer.GetValue();
            if (multiline) {
                propmap[String(key.mPtr, key.mLen)].Append(val.mPtr, val.mLen);
            } else {
                propmap[String(key.mPtr, key.mLen)].Copy(val.mPtr, val.mLen);
            }
            if (verbose) {
                (*verbose) << "Loading key ";
                verbose->write(key.mPtr, key.mLen);
                (*verbose) << " with value ";
                verbose->write(val.mPtr, val.mLen);
                (*verbose) << endl;
            }
        }
    }
    return 0;
}

void
Properties::setValue(const string& key, const string& value)
{
    String kstr;
    if (key.length() > size_t(kStringBufSize)) {
        kstr = key;
    } else {
        kstr.Copy(key.data(), key.size());
    }
    if (value.length() > size_t(kStringBufSize)) {
        propmap[kstr] = value;
    } else {
        propmap[kstr].Copy(value.data(), value.size());
    }
}

void
Properties::setValue(const Properties::String& key, const string& value)
{
    if (value.length() > size_t(kStringBufSize)) {
        propmap[key] = value;
    } else {
        propmap[key].Copy(value.data(), value.size());
    }
}

string
Properties::getValueSelf(const Properties::String& key, const string& def) const
{
    PropMap::const_iterator const i = find(key);
    if (i == propmap.end()) {
        return def;
    }
    if (i->second.size() > size_t(kStringBufSize)) {
        return i->second.GetStr();
    }
    return string(i->second.data(), i->second.size());
}

const char*
Properties::getValueSelf(const Properties::String& key, const char* def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : i->second.c_str());
}

int
Properties::getValueSelf(const Properties::String& key, int def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def :
        (int)strtol(i->second.c_str(), 0, intbase));
}

unsigned int
Properties::getValueSelf(const Properties::String& key, unsigned int def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def :
        (unsigned int)strtoul(i->second.c_str(), 0, intbase));
}

long
Properties::getValueSelf(const Properties::String& key, long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtol(i->second.c_str(), 0, intbase));
}

unsigned long
Properties::getValueSelf(const Properties::String& key, unsigned long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoul(i->second.c_str(), 0, intbase));
}

long long
Properties::getValueSelf(const Properties::String& key, long long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoll(i->second.c_str(), 0, intbase));
}

unsigned long long
Properties::getValueSelf(const Properties::String& key, unsigned long long def)
    const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoull(i->second.c_str(), 0, intbase));
}

double
Properties::getValueSelf(const Properties::String& key, double def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : atof(i->second.c_str()));
}

bool
Properties::remove(const Properties::String& key)
{
    return (propmap.erase(key) > 0);
}

void
Properties::getList(string& outBuf,
    const string& linePrefix, const string& lineSuffix) const
{
    PropMap::const_iterator iter;
    for (iter = propmap.begin(); iter != propmap.end(); iter++) {
        if (iter->first.size() > 0) {
            outBuf += linePrefix;
            outBuf.append(iter->first.data(), iter->first.size());
            outBuf += '=';
            outBuf.append(iter->second.data(), iter->second.size());
            outBuf += lineSuffix;
        }
  }
  return;
}

void
Properties::copyWithPrefix(const string& prefix, Properties& props) const
{
    const size_t prefixSize = prefix.size();
    PropMap::const_iterator iter;
    for (iter = propmap.begin(); iter != propmap.end(); iter++) {
        const String& key = iter->first;
        if (key.size() >= prefixSize &&
                prefix.compare(0, prefixSize, key.c_str()) == 0) {
            props.propmap[key] = iter->second;
        }
    }
}

} // namespace KFS
<commit_msg>Common lib: fix Properties::copyWithPrefix().<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// \brief Properties implementation.
//
// Created 2004/05/05
//
// Copyright 2008-2012 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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 <iostream>
#include <fstream>
#include <cstdlib>
#include "Properties.h"
#include "RequestParser.h"

namespace KFS
{

using std::string;
using std::istream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::endl;

inline static int
AsciiCharToLower(int c)
{
    return ((c >= 'A' && c <= 'Z') ? 'a' + (c - 'A') : c);
}

template<typename T> inline static void
removeLTSpaces(const string& str, string::size_type start,
    string::size_type end, T& outStr, bool asciiToLower = false)
{
    char const* const delims = " \t\r\n";

    if (start >= str.length()) {
        outStr.clear();
        return;
    }
    string::size_type const first = str.find_first_not_of(delims, start);
    if (end <= first || first == string::npos) {
        outStr.clear();
        return;
    }
    string::size_type const last = str.find_last_not_of(
        delims, end == string::npos ? string::npos : end - 1);
    if (asciiToLower) {
        outStr.clear();
        for (const char* p = str.data() + first,
                * e = str.data() +
                    (last == string::npos ? str.size() : last + 1);
                p < e;
                ++p) {
            outStr.Append(AsciiCharToLower(*p & 0xFF));
        }
        return;
    }
    outStr.Copy(str.c_str() + first,
        (last == string::npos ? str.size() : last + 1) - first);
}

/* static */ string
Properties::AsciiToLower(const string& str)
{
    string s(str);
    for (string::iterator i = s.begin(); i != s.end(); ++i) {
        const int c = AsciiCharToLower(*i & 0xFF);
        if (c != *i) {
            *i = c;
        }
    }
    return s;
}

inline Properties::iterator
Properties::find(const Properties::String& key) const
{
    return propmap.find(key);
}

Properties::Properties(int base)
    : intbase(base),
      propmap()
{
}

Properties::Properties(const Properties &p)
    : intbase(p.intbase),
      propmap(p.propmap)
{
}

Properties::~Properties()
{
}

int
Properties::loadProperties(
    const char* fileName,
    char        delimiter,
    bool        verbose /* = false */,
    bool        multiline /* =false */,
    bool        keysAsciiToLower /* = false */)
{
    ifstream input(fileName);
    if(! input.is_open()) {
        cerr <<  "Properties::loadProperties() failed to open the file:" <<
            fileName << endl;
        return(-1);
    }
    loadProperties(input, delimiter, verbose, multiline, keysAsciiToLower);
    input.close();
    return 0;
}

int
Properties::loadProperties(
    istream& ist,
    char     delimiter,
    bool     verbose,
    bool     multiline /* = false */,
    bool     keysAsciiToLower /* = false */)
{
    string line;
    String key;
    String val;
    if (ist) {
        line.reserve(512);
    }
    while (ist) {
        getline(ist, line); //read one line at a time
        if (line.empty() || line[0] == '#') {
            continue; // ignore comments
        }
        // find the delimiter
        string::size_type const pos = line.find(delimiter);
        if (pos == string::npos) {
            continue; // ignore if no delimiter is found
        }
        removeLTSpaces(line, 0, pos, key, keysAsciiToLower);
        removeLTSpaces(line, pos + 1, string::npos, val);
        if (multiline) {
            // allow properties to span across multiple lines
            propmap[key].Append(val);
        } else {
            propmap[key] = val;
        }
        if (verbose) {
            cout << "Loading key " << key  <<
                " with value " << propmap[key] << endl;
        }
    }
    return 0;
}

int
Properties::loadProperties(
    const char* buf,
    size_t      len,
    char        delimiter,
    ostream*    verbose /* = 0 */,
    bool        multiline /* = false */,
    bool        keysAsciiToLower /* = false */)
{
    PropertiesTokenizer tokenizer(buf, len);
    if (keysAsciiToLower) {
        String lkey;
        while (tokenizer.Next(delimiter)) {
            const PropertiesTokenizer::Token& key = tokenizer.GetKey();
            const PropertiesTokenizer::Token& val = tokenizer.GetValue();
            lkey.clear();
            for (const char* p = key.mPtr, * e = p + key.mLen; p < e; ++p) {
                lkey.Append(AsciiCharToLower(*p & 0xFF));
            }
            if (multiline) {
                propmap[lkey].Append(val.mPtr, val.mLen);
            } else {
                propmap[lkey].Copy(val.mPtr, val.mLen);
            }
            if (verbose) {
                (*verbose) << "Loading key ";
                verbose->write(key.mPtr, key.mLen);
                (*verbose) << " with value ";
                verbose->write(val.mPtr, val.mLen);
                (*verbose) << endl;
            }
        }
    } else {
        while (tokenizer.Next(delimiter)) {
            const PropertiesTokenizer::Token& key = tokenizer.GetKey();
            const PropertiesTokenizer::Token& val = tokenizer.GetValue();
            if (multiline) {
                propmap[String(key.mPtr, key.mLen)].Append(val.mPtr, val.mLen);
            } else {
                propmap[String(key.mPtr, key.mLen)].Copy(val.mPtr, val.mLen);
            }
            if (verbose) {
                (*verbose) << "Loading key ";
                verbose->write(key.mPtr, key.mLen);
                (*verbose) << " with value ";
                verbose->write(val.mPtr, val.mLen);
                (*verbose) << endl;
            }
        }
    }
    return 0;
}

void
Properties::setValue(const string& key, const string& value)
{
    String kstr;
    if (key.length() > size_t(kStringBufSize)) {
        kstr = key;
    } else {
        kstr.Copy(key.data(), key.size());
    }
    if (value.length() > size_t(kStringBufSize)) {
        propmap[kstr] = value;
    } else {
        propmap[kstr].Copy(value.data(), value.size());
    }
}

void
Properties::setValue(const Properties::String& key, const string& value)
{
    if (value.length() > size_t(kStringBufSize)) {
        propmap[key] = value;
    } else {
        propmap[key].Copy(value.data(), value.size());
    }
}

string
Properties::getValueSelf(const Properties::String& key, const string& def) const
{
    PropMap::const_iterator const i = find(key);
    if (i == propmap.end()) {
        return def;
    }
    if (i->second.size() > size_t(kStringBufSize)) {
        return i->second.GetStr();
    }
    return string(i->second.data(), i->second.size());
}

const char*
Properties::getValueSelf(const Properties::String& key, const char* def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : i->second.c_str());
}

int
Properties::getValueSelf(const Properties::String& key, int def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def :
        (int)strtol(i->second.c_str(), 0, intbase));
}

unsigned int
Properties::getValueSelf(const Properties::String& key, unsigned int def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def :
        (unsigned int)strtoul(i->second.c_str(), 0, intbase));
}

long
Properties::getValueSelf(const Properties::String& key, long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtol(i->second.c_str(), 0, intbase));
}

unsigned long
Properties::getValueSelf(const Properties::String& key, unsigned long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoul(i->second.c_str(), 0, intbase));
}

long long
Properties::getValueSelf(const Properties::String& key, long long def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoll(i->second.c_str(), 0, intbase));
}

unsigned long long
Properties::getValueSelf(const Properties::String& key, unsigned long long def)
    const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : strtoull(i->second.c_str(), 0, intbase));
}

double
Properties::getValueSelf(const Properties::String& key, double def) const
{
    PropMap::const_iterator const i = find(key);
    return (i == propmap.end() ? def : atof(i->second.c_str()));
}

bool
Properties::remove(const Properties::String& key)
{
    return (propmap.erase(key) > 0);
}

void
Properties::getList(string& outBuf,
    const string& linePrefix, const string& lineSuffix) const
{
    PropMap::const_iterator iter;
    for (iter = propmap.begin(); iter != propmap.end(); iter++) {
        if (iter->first.size() > 0) {
            outBuf += linePrefix;
            outBuf.append(iter->first.data(), iter->first.size());
            outBuf += '=';
            outBuf.append(iter->second.data(), iter->second.size());
            outBuf += lineSuffix;
        }
  }
  return;
}

void
Properties::copyWithPrefix(const string& prefix, Properties& props) const
{
    const size_t prefixSize = prefix.size();
    PropMap::const_iterator iter;
    for (iter = propmap.begin(); iter != propmap.end(); iter++) {
        const String& key = iter->first;
        if (key.size() >= prefixSize &&
                prefix.compare(0, prefixSize, key.c_str(), prefixSize) == 0) {
            props.propmap[key] = iter->second;
        }
    }
}

} // namespace KFS
<|endoftext|>


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

#include "chrome/browser/dom_ui/search_engine_manager_handler.h"

#include "app/l10n_util.h"
#include "base/callback.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/keyword_editor_controller.h"
#include "chrome/browser/search_engines/template_url_table_model.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

SearchEngineManagerHandler::SearchEngineManagerHandler() {
}

SearchEngineManagerHandler::~SearchEngineManagerHandler() {
  if (controller_.get() && controller_->table_model())
    controller_->table_model()->SetObserver(NULL);
}

void SearchEngineManagerHandler::Initialize() {
  controller_.reset(new KeywordEditorController(dom_ui_->GetProfile()));
  controller_->table_model()->SetObserver(this);
}

void SearchEngineManagerHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

  localized_strings->SetString("searchEngineManagerPage",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE));
  localized_strings->SetString("searchEngineTableNameHeader",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
  localized_strings->SetString("searchEngineTableKeywordHeader",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
  localized_strings->SetString("addSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON));
  localized_strings->SetString("removeSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON));
  localized_strings->SetString("editSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
  localized_strings->SetString("makeDefaultSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
}

void SearchEngineManagerHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback(
      "managerSetDefaultSearchEngine",
      NewCallback(this, &SearchEngineManagerHandler::SetDefaultSearchEngine));
  dom_ui_->RegisterMessageCallback(
      "removeSearchEngine",
      NewCallback(this, &SearchEngineManagerHandler::RemoveSearchEngine));
}

void SearchEngineManagerHandler::OnModelChanged() {
  ListValue engine_list;

  // Find the default engine.
  const TemplateURL* default_engine =
      controller_->url_model()->GetDefaultSearchProvider();
  int default_index = controller_->table_model()->IndexOfTemplateURL(
      default_engine);

  // Add the first group (default search engine options).
  engine_list.Append(CreateDictionaryForHeading(0));
  int last_default_engine_index =
      controller_->table_model()->last_search_engine_index();
  for (int i = 0; i < last_default_engine_index; ++i) {
    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
  }

  // Add the second group (other search templates).
  engine_list.Append(CreateDictionaryForHeading(1));
  if (last_default_engine_index < 0)
    last_default_engine_index = 0;
  int engine_count = controller_->table_model()->RowCount();
  for (int i = last_default_engine_index; i < engine_count; ++i) {
    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
  }

  dom_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList",
                                  engine_list);
}

void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
  OnModelChanged();
}

void SearchEngineManagerHandler::OnItemsAdded(int start, int length) {
  OnModelChanged();
}

void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
  OnModelChanged();
}

DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForHeading(
    int group_index) {
  TableModel::Groups groups = controller_->table_model()->GetGroups();

  DictionaryValue* dict = new DictionaryValue();
  dict->SetString("heading", WideToUTF16Hack(groups[group_index].title));
  return dict;
}

DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
    int index, bool is_default) {
  TemplateURLTableModel* table_model = controller_->table_model();

  DictionaryValue* dict = new DictionaryValue();
  dict->SetString("name", WideToUTF16Hack(table_model->GetText(
    index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)));
  dict->SetString("keyword", WideToUTF16Hack(table_model->GetText(
    index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)));
  const TemplateURL* template_url = controller_->GetTemplateURL(index);
  GURL icon_url = template_url->GetFavIconURL();
  if (icon_url.is_valid())
    dict->SetString("iconURL", icon_url.spec());
  dict->SetString("modelIndex", base::IntToString(index));

  if (controller_->CanRemove(template_url))
    dict->SetString("canBeRemoved", "1");
  if (controller_->CanMakeDefault(template_url))
    dict->SetString("canBeDefault", "1");
  if (is_default)
    dict->SetString("default", "1");

  return dict;
}

void SearchEngineManagerHandler::SetDefaultSearchEngine(const ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= controller_->table_model()->RowCount())
    return;

  controller_->MakeDefaultTemplateURL(index);
}

void SearchEngineManagerHandler::RemoveSearchEngine(const ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= controller_->table_model()->RowCount())
    return;

  if (controller_->CanRemove(controller_->GetTemplateURL(index)))
    controller_->RemoveTemplateURL(index);
}
<commit_msg>DOMUI prefs: Fix a race condition in pushing search engine information to DOMUI<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/dom_ui/search_engine_manager_handler.h"

#include "app/l10n_util.h"
#include "base/callback.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/keyword_editor_controller.h"
#include "chrome/browser/search_engines/template_url_table_model.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

SearchEngineManagerHandler::SearchEngineManagerHandler() {
}

SearchEngineManagerHandler::~SearchEngineManagerHandler() {
  if (controller_.get() && controller_->table_model())
    controller_->table_model()->SetObserver(NULL);
}

void SearchEngineManagerHandler::Initialize() {
  controller_.reset(new KeywordEditorController(dom_ui_->GetProfile()));
  if (controller_.get()) {
    controller_->table_model()->SetObserver(this);
    OnModelChanged();
  }
}

void SearchEngineManagerHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

  localized_strings->SetString("searchEngineManagerPage",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE));
  localized_strings->SetString("searchEngineTableNameHeader",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
  localized_strings->SetString("searchEngineTableKeywordHeader",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
  localized_strings->SetString("addSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON));
  localized_strings->SetString("removeSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON));
  localized_strings->SetString("editSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON));
  localized_strings->SetString("makeDefaultSearchEngineButton",
      l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON));
}

void SearchEngineManagerHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback(
      "managerSetDefaultSearchEngine",
      NewCallback(this, &SearchEngineManagerHandler::SetDefaultSearchEngine));
  dom_ui_->RegisterMessageCallback(
      "removeSearchEngine",
      NewCallback(this, &SearchEngineManagerHandler::RemoveSearchEngine));
}

void SearchEngineManagerHandler::OnModelChanged() {
  if (!controller_->loaded())
    return;

  ListValue engine_list;

  // Find the default engine.
  const TemplateURL* default_engine =
      controller_->url_model()->GetDefaultSearchProvider();
  int default_index = controller_->table_model()->IndexOfTemplateURL(
      default_engine);

  // Add the first group (default search engine options).
  engine_list.Append(CreateDictionaryForHeading(0));
  int last_default_engine_index =
      controller_->table_model()->last_search_engine_index();
  for (int i = 0; i < last_default_engine_index; ++i) {
    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
  }

  // Add the second group (other search templates).
  engine_list.Append(CreateDictionaryForHeading(1));
  if (last_default_engine_index < 0)
    last_default_engine_index = 0;
  int engine_count = controller_->table_model()->RowCount();
  for (int i = last_default_engine_index; i < engine_count; ++i) {
    engine_list.Append(CreateDictionaryForEngine(i, i == default_index));
  }

  dom_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList",
                                  engine_list);
}

void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
  OnModelChanged();
}

void SearchEngineManagerHandler::OnItemsAdded(int start, int length) {
  OnModelChanged();
}

void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
  OnModelChanged();
}

DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForHeading(
    int group_index) {
  TableModel::Groups groups = controller_->table_model()->GetGroups();

  DictionaryValue* dict = new DictionaryValue();
  dict->SetString("heading", WideToUTF16Hack(groups[group_index].title));
  return dict;
}

DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
    int index, bool is_default) {
  TemplateURLTableModel* table_model = controller_->table_model();

  DictionaryValue* dict = new DictionaryValue();
  dict->SetString("name", WideToUTF16Hack(table_model->GetText(
    index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)));
  dict->SetString("keyword", WideToUTF16Hack(table_model->GetText(
    index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)));
  const TemplateURL* template_url = controller_->GetTemplateURL(index);
  GURL icon_url = template_url->GetFavIconURL();
  if (icon_url.is_valid())
    dict->SetString("iconURL", icon_url.spec());
  dict->SetString("modelIndex", base::IntToString(index));

  if (controller_->CanRemove(template_url))
    dict->SetString("canBeRemoved", "1");
  if (controller_->CanMakeDefault(template_url))
    dict->SetString("canBeDefault", "1");
  if (is_default)
    dict->SetString("default", "1");

  return dict;
}

void SearchEngineManagerHandler::SetDefaultSearchEngine(const ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= controller_->table_model()->RowCount())
    return;

  controller_->MakeDefaultTemplateURL(index);
}

void SearchEngineManagerHandler::RemoveSearchEngine(const ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= controller_->table_model()->RowCount())
    return;

  if (controller_->CanRemove(controller_->GetTemplateURL(index)))
    controller_->RemoveTemplateURL(index);
}
<|endoftext|>


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

#include "base/command_line.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

#if defined(TOOLKIT_VIEWS)
#define MAYBE_Infobars Infobars
#else
// Need to finish port to Linux. See http://crbug.com/39916 for details.
// Temporarily marked as DISABLED on OSX too. See http://crbug.com/60990 for details.
#define MAYBE_Infobars DISABLED_Infobars
#endif

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Infobars) {
  // TODO(finnur): Remove once infobars are no longer experimental (bug 39511).
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("infobars")) << message_;
}
<commit_msg>Marking ExtensionApiTest, Infobars as DISABLED on everything but Windows.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"

#if defined(OS_WIN)
#define MAYBE_Infobars Infobars
#else
// Need to finish port to Linux. See http://crbug.com/39916 for details.
// Temporarily marked as DISABLED on OSX too. See http://crbug.com/60990 for details.
#define MAYBE_Infobars DISABLED_Infobars
#endif

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Infobars) {
  // TODO(finnur): Remove once infobars are no longer experimental (bug 39511).
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableExperimentalExtensionApis);

  ASSERT_TRUE(RunExtensionTest("infobars")) << message_;
}
<|endoftext|>


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

#include "chrome/browser/renderer_host/async_resource_handler.h"

#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/process.h"
#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/load_timing_observer.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/common/render_messages.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "webkit/glue/resource_loader_bridge.h"

using base::Time;
using base::TimeTicks;

namespace {

// When reading, we don't know if we are going to get EOF (0 bytes read), so
// we typically have a buffer that we allocated but did not use.  We keep
// this buffer around for the next read as a small optimization.
SharedIOBuffer* g_spare_read_buffer = NULL;

// The initial size of the shared memory buffer. (32 kilobytes).
const int kInitialReadBufSize = 32768;

// The maximum size of the shared memory buffer. (512 kilobytes).
const int kMaxReadBufSize = 524288;

}  // namespace

// Our version of IOBuffer that uses shared memory.
class SharedIOBuffer : public net::IOBuffer {
 public:
  explicit SharedIOBuffer(int buffer_size)
      : net::IOBuffer(),
        ok_(false),
        buffer_size_(buffer_size) {}

  bool Init() {
    if (shared_memory_.Create(std::wstring(), false, false, buffer_size_) &&
        shared_memory_.Map(buffer_size_)) {
      data_ = reinterpret_cast<char*>(shared_memory_.memory());
      // TODO(hawk): Remove after debugging bug 16371.
      CHECK(data_);
      ok_ = true;
    }
    return ok_;
  }

  base::SharedMemory* shared_memory() { return &shared_memory_; }
  bool ok() { return ok_; }
  int buffer_size() { return buffer_size_; }

 private:
  ~SharedIOBuffer() {
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(g_spare_read_buffer != this);
    data_ = NULL;
  }

  base::SharedMemory shared_memory_;
  bool ok_;
  int buffer_size_;
};

AsyncResourceHandler::AsyncResourceHandler(
    ResourceDispatcherHost::Receiver* receiver,
    int process_id,
    int routing_id,
    base::ProcessHandle process_handle,
    const GURL& url,
    ResourceDispatcherHost* resource_dispatcher_host)
    : receiver_(receiver),
      process_id_(process_id),
      routing_id_(routing_id),
      process_handle_(process_handle),
      rdh_(resource_dispatcher_host),
      next_buffer_size_(kInitialReadBufSize) {
}

AsyncResourceHandler::~AsyncResourceHandler() {
}

void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request,
                                              ResourceResponse* response) {
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

bool AsyncResourceHandler::OnUploadProgress(int request_id,
                                            uint64 position,
                                            uint64 size) {
  return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_,
                                                             request_id,
                                                             position, size));
}

bool AsyncResourceHandler::OnRequestRedirected(int request_id,
                                               const GURL& new_url,
                                               ResourceResponse* response,
                                               bool* defer) {
  *defer = true;
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));
  PopulateTimingInfo(request, response);
  return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(
      routing_id_, request_id, new_url, response->response_head));
}

bool AsyncResourceHandler::OnResponseStarted(int request_id,
                                             ResourceResponse* response) {
  // For changes to the main frame, inform the renderer of the new URL's
  // per-host settings before the request actually commits.  This way the
  // renderer will be able to set these precisely at the time the
  // request commits, avoiding the possibility of e.g. zooming the old content
  // or of having to layout the new content twice.
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));

  PopulateTimingInfo(request, response);

  ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request);
  if (info->resource_type() == ResourceType::MAIN_FRAME) {
    GURL request_url(request->url());
    ChromeURLRequestContext* context =
        static_cast<ChromeURLRequestContext*>(request->context());
    if (context) {
      receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL(
          info->route_id(), request_url,
          context->host_content_settings_map()->GetContentSettings(
              request_url)));
      receiver_->Send(new ViewMsg_SetZoomLevelForLoadingURL(info->route_id(),
          request_url, context->host_zoom_map()->GetZoomLevel(request_url)));
    }
  }

  receiver_->Send(new ViewMsg_Resource_ReceivedResponse(
      routing_id_, request_id, response->response_head));

  if (request->response_info().metadata) {
    std::vector<char> copy(request->response_info().metadata->data(),
                           request->response_info().metadata->data() +
                           request->response_info().metadata->size());
    receiver_->Send(new ViewMsg_Resource_ReceivedCachedMetadata(
        routing_id_, request_id, copy));
  }

  return true;
}

bool AsyncResourceHandler::OnWillStart(int request_id,
                                       const GURL& url,
                                       bool* defer) {
  return true;
}

bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
                                      int* buf_size, int min_size) {
  DCHECK(min_size == -1);

  if (g_spare_read_buffer) {
    DCHECK(!read_buffer_);
    read_buffer_.swap(&g_spare_read_buffer);
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());

    *buf = read_buffer_.get();
    *buf_size = read_buffer_->buffer_size();
  } else {
    read_buffer_ = new SharedIOBuffer(next_buffer_size_);
    if (!read_buffer_->Init()) {
      DLOG(ERROR) << "Couldn't allocate shared io buffer";
      read_buffer_ = NULL;
      return false;
    }
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());
    *buf = read_buffer_.get();
    *buf_size = next_buffer_size_;
  }

  return true;
}

bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
  if (!*bytes_read)
    return true;
  DCHECK(read_buffer_.get());

  if (read_buffer_->buffer_size() == *bytes_read) {
    // The network layer has saturated our buffer. Next time, we should give it
    // a bigger buffer for it to fill, to minimize the number of round trips we
    // do with the renderer process.
    next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
  }

  if (!rdh_->WillSendData(process_id_, request_id)) {
    // We should not send this data now, we have too many pending requests.
    return true;
  }

  base::SharedMemoryHandle handle;
  if (!read_buffer_->shared_memory()->GiveToProcess(process_handle_, &handle)) {
    // We wrongfully incremented the pending data count. Fake an ACK message
    // to fix this. We can't move this call above the WillSendData because
    // it's killing our read_buffer_, and we don't want that when we pause
    // the request.
    rdh_->DataReceivedACK(process_id_, request_id);
    // We just unmapped the memory.
    read_buffer_ = NULL;
    return false;
  }
  // We just unmapped the memory.
  read_buffer_ = NULL;

  receiver_->Send(new ViewMsg_Resource_DataReceived(
      routing_id_, request_id, handle, *bytes_read));

  return true;
}

bool AsyncResourceHandler::OnResponseCompleted(
    int request_id,
    const URLRequestStatus& status,
    const std::string& security_info) {
  receiver_->Send(new ViewMsg_Resource_RequestComplete(routing_id_,
                                                       request_id,
                                                       status,
                                                       security_info));

  // If we still have a read buffer, then see about caching it for later...
  if (g_spare_read_buffer) {
    read_buffer_ = NULL;
  } else if (read_buffer_.get()) {
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());
    read_buffer_.swap(&g_spare_read_buffer);
  }
  return true;
}

void AsyncResourceHandler::OnRequestClosed() {
}

// static
void AsyncResourceHandler::GlobalCleanup() {
  if (g_spare_read_buffer) {
    // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer().
    SharedIOBuffer* tmp = g_spare_read_buffer;
    g_spare_read_buffer = NULL;
    tmp->Release();
  }
}
<commit_msg>AsyncResourceHandler: When a URLRequest is canceled, the network code may complete the request with a CANCELED status but hold on to the actual buffer that was used for the operation (that's the whole point about using IOBuffers instead of a plain, non-refcounted buffer).<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/async_resource_handler.h"

#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/process.h"
#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/load_timing_observer.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/common/render_messages.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "webkit/glue/resource_loader_bridge.h"

using base::Time;
using base::TimeTicks;

namespace {

// When reading, we don't know if we are going to get EOF (0 bytes read), so
// we typically have a buffer that we allocated but did not use.  We keep
// this buffer around for the next read as a small optimization.
SharedIOBuffer* g_spare_read_buffer = NULL;

// The initial size of the shared memory buffer. (32 kilobytes).
const int kInitialReadBufSize = 32768;

// The maximum size of the shared memory buffer. (512 kilobytes).
const int kMaxReadBufSize = 524288;

}  // namespace

// Our version of IOBuffer that uses shared memory.
class SharedIOBuffer : public net::IOBuffer {
 public:
  explicit SharedIOBuffer(int buffer_size)
      : net::IOBuffer(),
        ok_(false),
        buffer_size_(buffer_size) {}

  bool Init() {
    if (shared_memory_.Create(std::wstring(), false, false, buffer_size_) &&
        shared_memory_.Map(buffer_size_)) {
      data_ = reinterpret_cast<char*>(shared_memory_.memory());
      DCHECK(data_);
      ok_ = true;
    }
    return ok_;
  }

  base::SharedMemory* shared_memory() { return &shared_memory_; }
  bool ok() { return ok_; }
  int buffer_size() { return buffer_size_; }

 private:
  ~SharedIOBuffer() {
    DCHECK(g_spare_read_buffer != this);
    data_ = NULL;
  }

  base::SharedMemory shared_memory_;
  bool ok_;
  int buffer_size_;
};

AsyncResourceHandler::AsyncResourceHandler(
    ResourceDispatcherHost::Receiver* receiver,
    int process_id,
    int routing_id,
    base::ProcessHandle process_handle,
    const GURL& url,
    ResourceDispatcherHost* resource_dispatcher_host)
    : receiver_(receiver),
      process_id_(process_id),
      routing_id_(routing_id),
      process_handle_(process_handle),
      rdh_(resource_dispatcher_host),
      next_buffer_size_(kInitialReadBufSize) {
}

AsyncResourceHandler::~AsyncResourceHandler() {
}

void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request,
                                              ResourceResponse* response) {
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

bool AsyncResourceHandler::OnUploadProgress(int request_id,
                                            uint64 position,
                                            uint64 size) {
  return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_,
                                                             request_id,
                                                             position, size));
}

bool AsyncResourceHandler::OnRequestRedirected(int request_id,
                                               const GURL& new_url,
                                               ResourceResponse* response,
                                               bool* defer) {
  *defer = true;
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));
  PopulateTimingInfo(request, response);
  return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(
      routing_id_, request_id, new_url, response->response_head));
}

bool AsyncResourceHandler::OnResponseStarted(int request_id,
                                             ResourceResponse* response) {
  // For changes to the main frame, inform the renderer of the new URL's
  // per-host settings before the request actually commits.  This way the
  // renderer will be able to set these precisely at the time the
  // request commits, avoiding the possibility of e.g. zooming the old content
  // or of having to layout the new content twice.
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));

  PopulateTimingInfo(request, response);

  ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request);
  if (info->resource_type() == ResourceType::MAIN_FRAME) {
    GURL request_url(request->url());
    ChromeURLRequestContext* context =
        static_cast<ChromeURLRequestContext*>(request->context());
    if (context) {
      receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL(
          info->route_id(), request_url,
          context->host_content_settings_map()->GetContentSettings(
              request_url)));
      receiver_->Send(new ViewMsg_SetZoomLevelForLoadingURL(info->route_id(),
          request_url, context->host_zoom_map()->GetZoomLevel(request_url)));
    }
  }

  receiver_->Send(new ViewMsg_Resource_ReceivedResponse(
      routing_id_, request_id, response->response_head));

  if (request->response_info().metadata) {
    std::vector<char> copy(request->response_info().metadata->data(),
                           request->response_info().metadata->data() +
                           request->response_info().metadata->size());
    receiver_->Send(new ViewMsg_Resource_ReceivedCachedMetadata(
        routing_id_, request_id, copy));
  }

  return true;
}

bool AsyncResourceHandler::OnWillStart(int request_id,
                                       const GURL& url,
                                       bool* defer) {
  return true;
}

bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
                                      int* buf_size, int min_size) {
  DCHECK_EQ(-1, min_size);

  if (g_spare_read_buffer) {
    DCHECK(!read_buffer_);
    read_buffer_.swap(&g_spare_read_buffer);
    DCHECK(read_buffer_->data());

    *buf = read_buffer_.get();
    *buf_size = read_buffer_->buffer_size();
  } else {
    read_buffer_ = new SharedIOBuffer(next_buffer_size_);
    if (!read_buffer_->Init()) {
      DLOG(ERROR) << "Couldn't allocate shared io buffer";
      read_buffer_ = NULL;
      return false;
    }
    DCHECK(read_buffer_->data());
    *buf = read_buffer_.get();
    *buf_size = next_buffer_size_;
  }

  return true;
}

bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
  if (!*bytes_read)
    return true;
  DCHECK(read_buffer_.get());

  if (read_buffer_->buffer_size() == *bytes_read) {
    // The network layer has saturated our buffer. Next time, we should give it
    // a bigger buffer for it to fill, to minimize the number of round trips we
    // do with the renderer process.
    next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
  }

  if (!rdh_->WillSendData(process_id_, request_id)) {
    // We should not send this data now, we have too many pending requests.
    return true;
  }

  base::SharedMemoryHandle handle;
  if (!read_buffer_->shared_memory()->GiveToProcess(process_handle_, &handle)) {
    // We wrongfully incremented the pending data count. Fake an ACK message
    // to fix this. We can't move this call above the WillSendData because
    // it's killing our read_buffer_, and we don't want that when we pause
    // the request.
    rdh_->DataReceivedACK(process_id_, request_id);
    // We just unmapped the memory.
    read_buffer_ = NULL;
    return false;
  }
  // We just unmapped the memory.
  read_buffer_ = NULL;

  receiver_->Send(new ViewMsg_Resource_DataReceived(
      routing_id_, request_id, handle, *bytes_read));

  return true;
}

bool AsyncResourceHandler::OnResponseCompleted(
    int request_id,
    const URLRequestStatus& status,
    const std::string& security_info) {
  receiver_->Send(new ViewMsg_Resource_RequestComplete(routing_id_,
                                                       request_id,
                                                       status,
                                                       security_info));

  // If we still have a read buffer, then see about caching it for later...
  // Note that we have to make sure the buffer is not still being used, so we
  // have to perform an explicit check on the status code.
  if (g_spare_read_buffer || URLRequestStatus::SUCCESS != status.status()) {
    read_buffer_ = NULL;
  } else if (read_buffer_.get()) {
    DCHECK(read_buffer_->data());
    read_buffer_.swap(&g_spare_read_buffer);
  }
  return true;
}

void AsyncResourceHandler::OnRequestClosed() {
}

// static
void AsyncResourceHandler::GlobalCleanup() {
  if (g_spare_read_buffer) {
    // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer().
    SharedIOBuffer* tmp = g_spare_read_buffer;
    g_spare_read_buffer = NULL;
    tmp->Release();
  }
}
<|endoftext|>


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

#include "chrome/browser/sync/glue/extension_change_processor.h"

#include <sstream>
#include <string>

#include "base/logging.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/extension_model_associator.h"
#include "chrome/browser/sync/glue/extension_util.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_source.h"

typedef sync_api::SyncManager::ExtraExtensionChangeRecordData
    ExtraExtensionChangeRecordData;

namespace browser_sync {

ExtensionChangeProcessor::ExtensionChangeProcessor(
    UnrecoverableErrorHandler* error_handler,
    ExtensionModelAssociator* extension_model_associator)
    : ChangeProcessor(error_handler),
      extension_model_associator_(extension_model_associator),
      profile_(NULL) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(error_handler);
  DCHECK(extension_model_associator_);
}

ExtensionChangeProcessor::~ExtensionChangeProcessor() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}

// TODO(akalin): We need to make sure events we receive from either
// the browser or the syncapi are done in order; this is tricky since
// some events (e.g., extension installation) are done asynchronously.

void ExtensionChangeProcessor::Observe(NotificationType type,
                                       const NotificationSource& source,
                                       const NotificationDetails& details) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(running());
  DCHECK(profile_);
  switch (type.value) {
    case NotificationType::EXTENSION_LOADED:
    case NotificationType::EXTENSION_UNLOADED: {
      DCHECK_EQ(Source<Profile>(source).ptr(), profile_);
      Extension* extension = Details<Extension>(details).ptr();
      CHECK(extension);
      if (!IsExtensionSyncable(*extension)) {
        return;
      }
      const std::string& id = extension->id();
      LOG(INFO) << "Got change notification of type " << type.value
                << " for extension " << id;
      if (!extension_model_associator_->OnClientUpdate(id)) {
        std::string error = std::string("Client update failed for ") + id;
        error_handler()->OnUnrecoverableError(FROM_HERE, error);
        return;
      }
      break;
    }
    default:
      LOG(DFATAL) << "Received unexpected notification of type "
                  << type.value;
      break;
  }
}

void ExtensionChangeProcessor::ApplyChangesFromSyncModel(
    const sync_api::BaseTransaction* trans,
    const sync_api::SyncManager::ChangeRecord* changes,
    int change_count) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (!running()) {
    return;
  }
  for (int i = 0; i < change_count; ++i) {
    const sync_api::SyncManager::ChangeRecord& change = changes[i];
    switch (change.action) {
      case sync_api::SyncManager::ChangeRecord::ACTION_ADD:
      case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
        sync_api::ReadNode node(trans);
        if (!node.InitByIdLookup(change.id)) {
          std::stringstream error;
          error << "Extension node lookup failed for change " << change.id
                << " of action type " << change.action;
          error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
          return;
        }
        DCHECK_EQ(node.GetModelType(), syncable::EXTENSIONS);
        const sync_pb::ExtensionSpecifics& specifics =
            node.GetExtensionSpecifics();
        if (!IsExtensionSpecificsValid(specifics)) {
          std::string error =
              std::string("Invalid server specifics: ") +
              ExtensionSpecificsToString(specifics);
          error_handler()->OnUnrecoverableError(FROM_HERE, error);
          return;
        }
        StopObserving();
        extension_model_associator_->OnServerUpdate(specifics);
        StartObserving();
        break;
      }
      case sync_api::SyncManager::ChangeRecord::ACTION_DELETE: {
        StopObserving();
        scoped_ptr<ExtraExtensionChangeRecordData>
            data(static_cast<ExtraExtensionChangeRecordData*>(change.extra));
        if (data.get()) {
          extension_model_associator_->OnServerRemove(data->extension_id);
        } else {
          std::stringstream error;
          error << "Could not get extension ID for deleted node "
                << change.id;
          error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
          LOG(DFATAL) << error.str();
        }
        StartObserving();
        break;
      }
    }
  }
}

void ExtensionChangeProcessor::StartImpl(Profile* profile) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile);
  profile_ = profile;
  StartObserving();
}

void ExtensionChangeProcessor::StopImpl() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  StopObserving();
  profile_ = NULL;
}

void ExtensionChangeProcessor::StartObserving() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile_);
  LOG(INFO) << "Observing EXTENSION_LOADED and EXTENSION_UNLOADED";
  // TODO(akalin): We miss notifications when we uninstall a disabled
  // extension since EXTENSION_UNLOADED isn't sent in that case.  Add
  // an EXTENSION_UNINSTALLED notification and listen to it.
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_LOADED,
      Source<Profile>(profile_));
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_UNLOADED,
      Source<Profile>(profile_));
}

void ExtensionChangeProcessor::StopObserving() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile_);
  LOG(INFO) << "Unobserving all notifications";
  notification_registrar_.RemoveAll();
}

}  // namespace browser_sync
<commit_msg>Make extension sync change processor listen to events for disabled extensions.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/glue/extension_change_processor.h"

#include <sstream>
#include <string>

#include "base/logging.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/extension_model_associator.h"
#include "chrome/browser/sync/glue/extension_util.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_source.h"

typedef sync_api::SyncManager::ExtraExtensionChangeRecordData
    ExtraExtensionChangeRecordData;

namespace browser_sync {

ExtensionChangeProcessor::ExtensionChangeProcessor(
    UnrecoverableErrorHandler* error_handler,
    ExtensionModelAssociator* extension_model_associator)
    : ChangeProcessor(error_handler),
      extension_model_associator_(extension_model_associator),
      profile_(NULL) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(error_handler);
  DCHECK(extension_model_associator_);
}

ExtensionChangeProcessor::~ExtensionChangeProcessor() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}

// TODO(akalin): We need to make sure events we receive from either
// the browser or the syncapi are done in order; this is tricky since
// some events (e.g., extension installation) are done asynchronously.

void ExtensionChangeProcessor::Observe(NotificationType type,
                                       const NotificationSource& source,
                                       const NotificationDetails& details) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(running());
  DCHECK(profile_);
  switch (type.value) {
    case NotificationType::EXTENSION_LOADED:
    case NotificationType::EXTENSION_UPDATE_DISABLED:
    case NotificationType::EXTENSION_UNLOADED:
    case NotificationType::EXTENSION_UNLOADED_DISABLED: {
      DCHECK_EQ(Source<Profile>(source).ptr(), profile_);
      Extension* extension = Details<Extension>(details).ptr();
      CHECK(extension);
      if (!IsExtensionSyncable(*extension)) {
        return;
      }
      const std::string& id = extension->id();
      LOG(INFO) << "Got change notification of type " << type.value
                << " for extension " << id;
      if (!extension_model_associator_->OnClientUpdate(id)) {
        std::string error = std::string("Client update failed for ") + id;
        error_handler()->OnUnrecoverableError(FROM_HERE, error);
        return;
      }
      break;
    }
    default:
      LOG(DFATAL) << "Received unexpected notification of type "
                  << type.value;
      break;
  }
}

void ExtensionChangeProcessor::ApplyChangesFromSyncModel(
    const sync_api::BaseTransaction* trans,
    const sync_api::SyncManager::ChangeRecord* changes,
    int change_count) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  if (!running()) {
    return;
  }
  for (int i = 0; i < change_count; ++i) {
    const sync_api::SyncManager::ChangeRecord& change = changes[i];
    switch (change.action) {
      case sync_api::SyncManager::ChangeRecord::ACTION_ADD:
      case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
        sync_api::ReadNode node(trans);
        if (!node.InitByIdLookup(change.id)) {
          std::stringstream error;
          error << "Extension node lookup failed for change " << change.id
                << " of action type " << change.action;
          error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
          return;
        }
        DCHECK_EQ(node.GetModelType(), syncable::EXTENSIONS);
        const sync_pb::ExtensionSpecifics& specifics =
            node.GetExtensionSpecifics();
        if (!IsExtensionSpecificsValid(specifics)) {
          std::string error =
              std::string("Invalid server specifics: ") +
              ExtensionSpecificsToString(specifics);
          error_handler()->OnUnrecoverableError(FROM_HERE, error);
          return;
        }
        StopObserving();
        extension_model_associator_->OnServerUpdate(specifics);
        StartObserving();
        break;
      }
      case sync_api::SyncManager::ChangeRecord::ACTION_DELETE: {
        StopObserving();
        scoped_ptr<ExtraExtensionChangeRecordData>
            data(static_cast<ExtraExtensionChangeRecordData*>(change.extra));
        if (data.get()) {
          extension_model_associator_->OnServerRemove(data->extension_id);
        } else {
          std::stringstream error;
          error << "Could not get extension ID for deleted node "
                << change.id;
          error_handler()->OnUnrecoverableError(FROM_HERE, error.str());
          LOG(DFATAL) << error.str();
        }
        StartObserving();
        break;
      }
    }
  }
}

void ExtensionChangeProcessor::StartImpl(Profile* profile) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile);
  profile_ = profile;
  StartObserving();
}

void ExtensionChangeProcessor::StopImpl() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  StopObserving();
  profile_ = NULL;
}

void ExtensionChangeProcessor::StartObserving() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile_);
  LOG(INFO) << "Observing EXTENSION_LOADED, EXTENSION_UPDATE_DISABLED, "
            << "EXTENSION_UNLOADED, and EXTENSION_UNLOADED_DISABLED";
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_LOADED,
      Source<Profile>(profile_));
  // Despite the name, this notification is exactly like
  // EXTENSION_LOADED but with an initial state of DISABLED.
  //
  // TODO(akalin): See if the themes change processor needs to listen
  // to any of these, too.
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_UPDATE_DISABLED,
      Source<Profile>(profile_));
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_UNLOADED,
      Source<Profile>(profile_));
  notification_registrar_.Add(
      this, NotificationType::EXTENSION_UNLOADED_DISABLED,
      Source<Profile>(profile_));
}

void ExtensionChangeProcessor::StopObserving() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
  DCHECK(profile_);
  LOG(INFO) << "Unobserving all notifications";
  notification_registrar_.RemoveAll();
}

}  // namespace browser_sync
<|endoftext|>