<commit_before>/*
 * File:  cl_client.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "sedna.h"
#include <string>
#include <list>
#include <fstream>
#include <stdio.h>

#include "cl_client.h"
#include "base.h"
#include "ipc_ops.h"
#include "tr_globals.h"
#include "tr_functions.h"
#include "uhdd.h"
#include "version.h"

#define BATCH_DELIMITER "\\"

using namespace std;

command_line_client::command_line_client(int argc, char** argv)
{
  char buf[1024];

  if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) == 0)
  {//!!! metadata transaction case !!!
     if (argc != 2)
        throw SYSTEM_EXCEPTION("Bad number of input parameters to load metadata");

     strcpy(db_name, argv[1]);
     strcpy(filename, "dummy");
     strcpy(q_type, "XQuery");
     s = NULL;

  }
  else
  {
     //parse command line arguments
     if (is_command_line_args_length_overflow(argc, argv))
        throw USER_EXCEPTION(SE4600);

     if (argc == 1)
        print_tr_usage();
     else
     {
        int arg_scan_ret_val = 0; // 1 - parsed successful, 0 - there was errors
        char errmsg[1000];
        arg_scan_ret_val = arg_scanargv(argc, argv, tr_argtable, narg, NULL, errmsg, NULL);
        if (tr_s_help == 1 || tr_l_help == 1) print_tr_usage();
        if (tr_version == 1) { print_version_and_copyright("Sedna Transaction"); throw USER_SOFT_EXCEPTION(""); }
        if (arg_scan_ret_val == 0)
           throw USER_EXCEPTION2(SE4601, errmsg);
     }
     s = NULL;
  }
}

void command_line_client::init()
{
//  u_timeb ttt1, ttt2;
//  u_ftime(&ttt1);

   //check the correctness of input parameters from command line
   if (string(filename) == "???" || string(db_name) == "???")
     throw USER_EXCEPTION(SE4601);

   if (string(q_type) == "XQuery") query_type = TL_XQuery;
   else if (string(q_type) == "POR") query_type = TL_POR;
   else if (string(q_type) == "LR") query_type = TL_ForSemAnal;
   else throw USER_EXCEPTION(SE4002);

   string plain_batch_text;

   char buf[1024];
   if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) != 0)
   {
      //init output res
      if (string(output_file) == "STDOUT") res_os = stdout;
      else if ((res_os = fopen(output_file, "w")) == NULL) throw USER_EXCEPTION2(SE4040, output_file);

      //read batch text in string
      FILE *f;
      if ((f = fopen(filename, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, filename);

      char buf[1000000];
      plain_batch_text.reserve(100000);

      while(!feof(f)){

        size_t len= fread(buf, sizeof(char), sizeof(buf), f);

        plain_batch_text.append(buf, len);
      }
   }
   else
   {
#if (AUTH_SWITCH == 1)
      string path_to_security_file;
      char path_buf[U_MAX_PATH + 32];
      path_to_security_file = uGetImageProcPath(path_buf, __sys_call_error) + string("/../share/") + string(INITIAL_SECURITY_METADATA_FILE_NAME);

#ifdef _WIN32
      int i;
      for (i=0; i<path_to_security_file.size(); i++)
        if (path_to_security_file[i] == '\\') path_to_security_file[i] = '/';
#else
      if(!uIsFileExist(path_to_security_file.c_str(), __sys_call_error))
         path_to_security_file = string("/usr/share/sedna-") + SEDNA_VERSION + "." + SEDNA_BUILD +string("/sedna_auth_md.xml");
#endif

      plain_batch_text = string("LOAD ") +
                         string("\"") + path_to_security_file + string("\" ") +
                         string("\"") + string(SECURITY_METADATA_DOCUMENT) + string("\"");
#else
      plain_batch_text = "0";
#endif
   }

//   StringVector stmnts_array = parse_batch(query_type, plain_batch_text.c_str());
   stmnts_array = parse_batch(query_type, plain_batch_text.c_str());

   //add 'coomit' command if there is not end of transaction (coommit or rollback) command
   if (stmnts_array.back().substr(0, 8).find("rollback") == string::npos &&
       stmnts_array.back().substr(0, 6).find("commit") == string::npos)
       stmnts_array.push_back("commit");

   cl_command cmd;

   //!!!init stack!!!
   //put close session on buttom
   cmd.type = se_CloseConnection;
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   //put terminate transaction cmd
   if (stmnts_array.back().substr(0, 8).find("rollback") == string::npos &&
       stmnts_array.back().substr(0, 6).find("commit") == string::npos)
   {
      cmd.type = 220;//commit
   }
   else //commit or rollback exists in script
   {
      if (stmnts_array.back().substr(0, 6).find("commit") != string::npos)
         cmd.type = se_CommitTransaction;//commit
      else
         cmd.type = se_RollbackTransaction;//rollback

      stmnts_array.pop_back();//delete terminate command
   }

   cmd.length = 0;

   cl_cmds.push_front(cmd);

   //put queries to stack
   for (int i=stmnts_array.size()-1; i>=0; i--)
   {
      cmd.type = se_Execute;
      cmd.length = stmnts_array[i].size();
      cl_cmds.push_front(cmd);

   }

   statement_index = 0;
   //put tr begin
   cmd.type = se_BeginTransaction;
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   //put authenticate transaction on top of stack

   cmd.type = se_CommitTransaction;//commit tr
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   cmd.type = se_Authenticate;//authenticate
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   cmd.type = se_BeginTransaction;//begin tr
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   s = new se_stdlib_ostream(std::cout);
//  u_ftime(&ttt2);
//  cerr << "init!!!!!!!!!!!!: " << to_string(ttt2 - ttt1).c_str() << endl;
}

void command_line_client::release()
{
   if (s != NULL)
   {
       delete s;
       s = NULL;
   }
}

void command_line_client::read_msg(msg_struct *msg)
{
  if (is_stop_session())//session closed forcedly by se_stop utility
  {
     clear_stack_for_stop_signal();
  }

  msg->instruction = cl_cmds.front().type;
  msg->length = cl_cmds.front().length;
  cl_cmds.pop_front();
}

char* command_line_client::get_query_string(msg_struct *msg)
{
   return (char*)stmnts_array[statement_index++].c_str();
}

t_print command_line_client::get_result_type(msg_struct *msg)
{
	return xml;
}

QueryType command_line_client::get_query_type()
{
  if (query_type == TL_POR) return TL_POR;
  else return TL_ForSemAnal;
}

se_ostream* command_line_client::get_se_ostream()
{
  return s;
}

client_file command_line_client::get_file_from_client(const char* client_filename)
{
  client_file cf;
  char buf[1024];

  if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) == 0)
  {//load metadata case (client_filename must be absolute path)
     if ((cf.f = fopen (client_filename, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, client_filename);
     strcpy(cf.name, client_filename);
     return cf;
  }

  char cur_dir_abspath[U_MAX_PATH];
  char qfile_abspath[U_MAX_PATH];
  char cfile_abspath[U_MAX_PATH];
  char dir[U_MAX_PATH];
  char *res = NULL;

  res = uGetCurrentWorkingDirectory(cur_dir_abspath, U_MAX_PATH, __sys_call_error);
  if (res == NULL)
     throw USER_EXCEPTION(SE4602);

  res = uGetAbsoluteFilePath(filename, qfile_abspath, U_MAX_PATH, __sys_call_error);
  if (res == NULL)
     throw USER_EXCEPTION2(SE4603, filename);

  char* new_dir;
  new_dir = uGetDirectoryFromFilePath(qfile_abspath, dir, U_MAX_PATH, __sys_call_error);

  if (uChangeWorkingDirectory(new_dir, __sys_call_error) != 0)
     throw USER_EXCEPTION2(SE4604, new_dir);

  res = uGetAbsoluteFilePath(client_filename, cfile_abspath, U_MAX_PATH, __sys_call_error);
  if (res == NULL)
     throw USER_EXCEPTION2(SE4603, client_filename);

  if (uChangeWorkingDirectory(cur_dir_abspath, __sys_call_error) != 0)
     throw USER_EXCEPTION2(SE4604, cur_dir_abspath);

  if ((cf.f = fopen(cfile_abspath, "r")) == NULL)
  {
     res = uGetAbsoluteFilePath(client_filename, cfile_abspath, U_MAX_PATH, __sys_call_error);
     if (res == NULL)
        throw USER_EXCEPTION2(SE4603, client_filename);

     if ((cf.f = fopen(cfile_abspath, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, client_filename);
  }

/*
  cf.f = fopen(cfile_abspath, "r");

  cf.f = fopen(client_filename, "r");

  if (cf.f == NULL)
	  throw CharismaException("#????: Can't open file to be loaded");
*/
  strcpy(cf.name, client_filename);

  return cf;
}

void command_line_client::close_file_from_client(client_file cf)
{
    if (fclose(cf.f) != 0) throw USER_EXCEPTION(SE3020);
}

void command_line_client::respond_to_client(int instruction)
{
    switch (instruction)
    {
        case se_UpdateSucceeded:
            fprintf(res_os, "\nUPDATE is executed successfully\n");
            break;
        case se_BulkLoadSucceeded:
            d_printf1("\nBulk load succeeded\n");
            break;
        case se_BeginTransactionOk:
            d_printf1("\nTr is started successfully\n");
            break;
        case se_CommitTransactionOk:
            d_printf1("\nTr is committed successfully\n");
            break;
        case se_RollbackTransactionOk:
            d_printf1("\nTr is rolled back successfully\n");
            break;
        case se_TransactionRollbackBeforeClose:
            d_printf1("\nTr is rolled back successfully\n");
            d_printf1("\nSession is closed successfully\n");
            break;
        case se_CloseConnectionOk:
            d_printf1("\nSession is closed successfully\n");
            break;
        default:
            d_printf2("\nUnknown instruction = %d\n", instruction);
            break;
    }
}

void command_line_client::begin_item()
{
}

void command_line_client::end_of_item(bool exist_next)
{

  if (exist_next)
  {//put next portion on top of stack
     cl_command cmd;
     cmd.type = se_GetNextItem;
     cmd.length = 0;
     cl_cmds.push_front(cmd);
  }
}

void command_line_client::authentication_result(bool res, const string& body)
{
   if (res)
      d_printf1("\nAuthentication is passed successfully\n");
   else
      d_printf2("\nAuthentication failed: %s\n", body.c_str());
}

void command_line_client::get_session_parameters()
{
}

void command_line_client::process_unknown_instruction(int instruction, bool in_transaction)
{
    throw USER_ENV_EXCEPTION("Command line client got unknown instruction.", true);
}

void command_line_client::error(int code, const string& body)
{
  //erase all commands from stack and push close session to stack
  //  (last transaction to this point already finished)
  cl_cmds.clear();

  cl_command cmd;
  cmd.type = se_CloseConnection;
  cmd.length = 0;

  cl_cmds.push_front(cmd);
}

void command_line_client::clear_stack_for_stop_signal()
{
   cl_command cmd;

   if (cl_cmds.front().type == se_Execute || //exexute query
       cl_cmds.front().type == se_GetNextItem || //next portion
       cl_cmds.front().type == se_Authenticate  || //authenticate
       cl_cmds.front().type == se_CommitTransaction || //commit
       cl_cmds.front().type == se_RollbackTransaction    //rollback
      )
   {//exist not finished transaction
    //put rollback (for not finished transaction) and close session
      cl_cmds.clear();
      cmd.type = se_CloseConnection;
      cmd.length = 0;
      cl_cmds.push_front(cmd);

      cmd.type = se_RollbackTransaction;
      cmd.length = 0;
      cl_cmds.push_front(cmd);
   }
   else
   {//there is not active transaction
    //put close session on stack
      cl_cmds.clear();
      cmd.type = se_CloseConnection;
      cmd.length = 0;
      cl_cmds.push_front(cmd);
   }
}

void command_line_client::show_time(string qep_time)
{
	d_printf2("Execution time of the latest query %s\n",qep_time.c_str());
}

void command_line_client::write_user_query_to_log()
{
   char buf[1000000];

   if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) != 0)
   {

      //read batch text in string

      FILE *f;
      if ((f = fopen(filename, "r")) == NULL)
         throw USER_EXCEPTION2(SE4042, filename);

      string plain_batch_text;
      plain_batch_text.reserve(100000);

      while(!feof(f))
      {
         size_t len= fread(buf, sizeof(char), sizeof(buf), f);
         plain_batch_text.append(buf, len);
      }

      elog_long(EL_LOG, "User's query:\n", plain_batch_text.c_str());
   }

}<commit_msg>finished partially with mm<commit_after>/*
 * File:  cl_client.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "sedna.h"
#include <string>
#include <list>
#include <fstream>
#include <stdio.h>

#include "cl_client.h"
#include "base.h"
#include "ipc_ops.h"
#include "tr_globals.h"
#include "tr_functions.h"
#include "uhdd.h"
#include "version.h"

#define BATCH_DELIMITER "\\"

using namespace std;

command_line_client::command_line_client(int argc, char** argv)
{
  char buf[1024];

  if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) == 0)
  {//!!! metadata transaction case !!!
     if (argc != 2)
        throw SYSTEM_EXCEPTION("Bad number of input parameters to load metadata");

     strcpy(db_name, argv[1]);
     strcpy(filename, "dummy");
     strcpy(q_type, "XQuery");
     s = NULL;

  }
  else
  {
     //parse command line arguments
     if (is_command_line_args_length_overflow(argc, argv))
        throw USER_EXCEPTION(SE4600);

     if (argc == 1)
        print_tr_usage();
     else
     {
        int arg_scan_ret_val = 0; // 1 - parsed successful, 0 - there was errors
        char errmsg[1000];
        arg_scan_ret_val = arg_scanargv(argc, argv, tr_argtable, narg, NULL, errmsg, NULL);
        if (tr_s_help == 1 || tr_l_help == 1) print_tr_usage();
        if (tr_version == 1) { print_version_and_copyright("Sedna Transaction"); throw USER_SOFT_EXCEPTION(""); }
        if (arg_scan_ret_val == 0)
           throw USER_EXCEPTION2(SE4601, errmsg);
     }
     s = NULL;
  }
}

void command_line_client::init()
{
//  u_timeb ttt1, ttt2;
//  u_ftime(&ttt1);

   //check the correctness of input parameters from command line
   if (string(filename) == "???" || string(db_name) == "???")
     throw USER_EXCEPTION(SE4601);

   if (string(q_type) == "XQuery") query_type = TL_XQuery;
   else if (string(q_type) == "POR") query_type = TL_POR;
   else if (string(q_type) == "LR") query_type = TL_ForSemAnal;
   else throw USER_EXCEPTION(SE4002);

   string plain_batch_text;

   char buf[1024];
   if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) != 0)
   {
      //init output res
      if (string(output_file) == "STDOUT") res_os = stdout;
      else if ((res_os = fopen(output_file, "w")) == NULL) throw USER_EXCEPTION2(SE4040, output_file);

      //read batch text in string
      FILE *f;
      if ((f = fopen(filename, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, filename);

      char buf[1000000];
      plain_batch_text.reserve(100000);

      while(!feof(f)){

        size_t len= fread(buf, sizeof(char), sizeof(buf), f);

        plain_batch_text.append(buf, len);
      }
   }
   else
   {
#if (AUTH_SWITCH == 1)
      string path_to_security_file;
      char path_buf[U_MAX_PATH + 32];
      path_to_security_file = uGetImageProcPath(path_buf, __sys_call_error) + string("/../share/") + string(INITIAL_SECURITY_METADATA_FILE_NAME);

#ifdef _WIN32
      int i;
      for (i=0; i<path_to_security_file.size(); i++)
        if (path_to_security_file[i] == '\\') path_to_security_file[i] = '/';
#else
      if(!uIsFileExist(path_to_security_file.c_str(), __sys_call_error))
         path_to_security_file = string("/usr/share/sedna-") + SEDNA_VERSION + "." + SEDNA_BUILD +string("/sedna_auth_md.xml");
#endif

      plain_batch_text = string("LOAD ") +
                         string("\"") + path_to_security_file + string("\" ") +
                         string("\"") + string(SECURITY_METADATA_DOCUMENT) + string("\"");
#else
      plain_batch_text = "0";
#endif
   }

//   StringVector stmnts_array = parse_batch(query_type, plain_batch_text.c_str());
   stmnts_array = parse_batch(query_type, plain_batch_text.c_str());

   //add 'coomit' command if there is not end of transaction (coommit or rollback) command
   if (stmnts_array.back().substr(0, 8).find("rollback") == string::npos &&
       stmnts_array.back().substr(0, 6).find("commit") == string::npos)
       stmnts_array.push_back("commit");

   cl_command cmd;

   //!!!init stack!!!
   //put close session on buttom
   cmd.type = se_CloseConnection;
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   //put terminate transaction cmd
   if (stmnts_array.back().substr(0, 8).find("rollback") == string::npos &&
       stmnts_array.back().substr(0, 6).find("commit") == string::npos)
   {
      cmd.type = 220;//commit
   }
   else //commit or rollback exists in script
   {
      if (stmnts_array.back().substr(0, 6).find("commit") != string::npos)
         cmd.type = se_CommitTransaction;//commit
      else
         cmd.type = se_RollbackTransaction;//rollback

      stmnts_array.pop_back();//delete terminate command
   }

   cmd.length = 0;

   cl_cmds.push_front(cmd);

   //put queries to stack
   for (int i=stmnts_array.size()-1; i>=0; i--)
   {
      cmd.type = se_Execute;
      cmd.length = stmnts_array[i].size();
      cl_cmds.push_front(cmd);

   }

   statement_index = 0;
   //put tr begin
   cmd.type = se_BeginTransaction;
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   //put authenticate transaction on top of stack

   cmd.type = se_CommitTransaction;//commit tr
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   cmd.type = se_Authenticate;//authenticate
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   cmd.type = se_BeginTransaction;//begin tr
   cmd.length = 0;
   cl_cmds.push_front(cmd);

   s = new se_stdlib_ostream(std::cout);
//  u_ftime(&ttt2);
//  cerr << "init!!!!!!!!!!!!: " << to_string(ttt2 - ttt1).c_str() << endl;
}

void command_line_client::release()
{
   if (s != NULL)
   {
       delete s;
       s = NULL;
   }
}

void command_line_client::read_msg(msg_struct *msg)
{
  if (is_stop_session())//session closed forcedly by se_stop utility
  {
     clear_stack_for_stop_signal();
  }

  msg->instruction = cl_cmds.front().type;
  msg->length = cl_cmds.front().length;
  cl_cmds.pop_front();
}

char* command_line_client::get_query_string(msg_struct *msg)
{
   return (char*)stmnts_array[statement_index++].c_str();
}

t_print command_line_client::get_result_type(msg_struct *msg)
{
	return xml;
}

QueryType command_line_client::get_query_type()
{
  if (query_type == TL_POR) return TL_POR;
  else return TL_ForSemAnal;
}

se_ostream* command_line_client::get_se_ostream()
{
  return s;
}

client_file command_line_client::get_file_from_client(const char* client_filename)
{
  client_file cf;
  char buf[1024];

  if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) == 0)
  {//load metadata case (client_filename must be absolute path)
     if ((cf.f = fopen (client_filename, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, client_filename);
     strcpy(cf.name, client_filename);
     return cf;
  }

  char cur_dir_abspath[U_MAX_PATH];
  char qfile_abspath[U_MAX_PATH];
  char cfile_abspath[U_MAX_PATH];
  char dir[U_MAX_PATH];
  char *res = NULL;

  res = uGetCurrentWorkingDirectory(cur_dir_abspath, U_MAX_PATH, __sys_call_error);
  if (res == NULL)
     throw USER_EXCEPTION(SE4602);

  res = uGetAbsoluteFilePath(filename, qfile_abspath, U_MAX_PATH, __sys_call_error);
  if (res == NULL)
     throw USER_EXCEPTION2(SE4603, filename);

  char* new_dir;
  new_dir = uGetDirectoryFromFilePath(qfile_abspath, dir, U_MAX_PATH, __sys_call_error);

  if (uChangeWorkingDirectory(new_dir, __sys_call_error) != 0)
     throw USER_EXCEPTION2(SE4604, new_dir);

  res = uGetAbsoluteFilePath(client_filename, cfile_abspath, U_MAX_PATH, __sys_call_error);
/*if (res == NULL)
     throw USER_EXCEPTION2(SE4603, client_filename);
*/

  if (uChangeWorkingDirectory(cur_dir_abspath, __sys_call_error) != 0)
     throw USER_EXCEPTION2(SE4604, cur_dir_abspath);

  if ((cf.f = fopen(cfile_abspath, "r")) == NULL)
  {
     res = uGetAbsoluteFilePath(client_filename, cfile_abspath, U_MAX_PATH, __sys_call_error);
/*     if (res == NULL)
        throw USER_EXCEPTION2(SE4603, client_filename);
*/

     if ((cf.f = fopen(cfile_abspath, "r")) == NULL)
        throw USER_EXCEPTION2(SE4042, client_filename);
  }

/*
  cf.f = fopen(cfile_abspath, "r");

  cf.f = fopen(client_filename, "r");

  if (cf.f == NULL)
	  throw CharismaException("#????: Can't open file to be loaded");
*/
  strcpy(cf.name, client_filename);

  return cf;
}

void command_line_client::close_file_from_client(client_file cf)
{
    if (fclose(cf.f) != 0) throw USER_EXCEPTION(SE3020);
}

void command_line_client::respond_to_client(int instruction)
{
    switch (instruction)
    {
        case se_UpdateSucceeded:
            fprintf(res_os, "\nUPDATE is executed successfully\n");
            break;
        case se_BulkLoadSucceeded:
            d_printf1("\nBulk load succeeded\n");
            break;
        case se_BeginTransactionOk:
            d_printf1("\nTr is started successfully\n");
            break;
        case se_CommitTransactionOk:
            d_printf1("\nTr is committed successfully\n");
            break;
        case se_RollbackTransactionOk:
            d_printf1("\nTr is rolled back successfully\n");
            break;
        case se_TransactionRollbackBeforeClose:
            d_printf1("\nTr is rolled back successfully\n");
            d_printf1("\nSession is closed successfully\n");
            break;
        case se_CloseConnectionOk:
            d_printf1("\nSession is closed successfully\n");
            break;
        default:
            d_printf2("\nUnknown instruction = %d\n", instruction);
            break;
    }
}

void command_line_client::begin_item()
{
}

void command_line_client::end_of_item(bool exist_next)
{

  if (exist_next)
  {//put next portion on top of stack
     cl_command cmd;
     cmd.type = se_GetNextItem;
     cmd.length = 0;
     cl_cmds.push_front(cmd);
  }
}

void command_line_client::authentication_result(bool res, const string& body)
{
   if (res)
      d_printf1("\nAuthentication is passed successfully\n");
   else
      d_printf2("\nAuthentication failed: %s\n", body.c_str());
}

void command_line_client::get_session_parameters()
{
}

void command_line_client::process_unknown_instruction(int instruction, bool in_transaction)
{
    throw USER_ENV_EXCEPTION("Command line client got unknown instruction.", true);
}

void command_line_client::error(int code, const string& body)
{
  //erase all commands from stack and push close session to stack
  //  (last transaction to this point already finished)
  cl_cmds.clear();

  cl_command cmd;
  cmd.type = se_CloseConnection;
  cmd.length = 0;

  cl_cmds.push_front(cmd);
}

void command_line_client::clear_stack_for_stop_signal()
{
   cl_command cmd;

   if (cl_cmds.front().type == se_Execute || //exexute query
       cl_cmds.front().type == se_GetNextItem || //next portion
       cl_cmds.front().type == se_Authenticate  || //authenticate
       cl_cmds.front().type == se_CommitTransaction || //commit
       cl_cmds.front().type == se_RollbackTransaction    //rollback
      )
   {//exist not finished transaction
    //put rollback (for not finished transaction) and close session
      cl_cmds.clear();
      cmd.type = se_CloseConnection;
      cmd.length = 0;
      cl_cmds.push_front(cmd);

      cmd.type = se_RollbackTransaction;
      cmd.length = 0;
      cl_cmds.push_front(cmd);
   }
   else
   {//there is not active transaction
    //put close session on stack
      cl_cmds.clear();
      cmd.type = se_CloseConnection;
      cmd.length = 0;
      cl_cmds.push_front(cmd);
   }
}

void command_line_client::show_time(string qep_time)
{
	d_printf2("Execution time of the latest query %s\n",qep_time.c_str());
}

void command_line_client::write_user_query_to_log()
{
   char buf[1000000];

   if (uGetEnvironmentVariable(SEDNA_LOAD_METADATA_TRANSACTION, buf, 1024, __sys_call_error) != 0)
   {

      //read batch text in string

      FILE *f;
      if ((f = fopen(filename, "r")) == NULL)
         throw USER_EXCEPTION2(SE4042, filename);

      string plain_batch_text;
      plain_batch_text.reserve(100000);

      while(!feof(f))
      {
         size_t len= fread(buf, sizeof(char), sizeof(buf), f);
         plain_batch_text.append(buf, len);
      }

      elog_long(EL_LOG, "User's query:\n", plain_batch_text.c_str());
   }

}
<|endoftext|>


<commit_before>#include "flakeref.hh"
#include "store-api.hh"
#include "fetchers/parse.hh"
#include "fetchers/fetchers.hh"
#include "fetchers/registry.hh"
#include "fetchers/regex.hh"

namespace nix {

#if 0
// 'dir' path elements cannot start with a '.'. We also reject
// potentially dangerous characters like ';'.
const static std::string subDirElemRegex = "(?:[a-zA-Z0-9_-]+[a-zA-Z0-9._-]*)";
const static std::string subDirRegex = subDirElemRegex + "(?:/" + subDirElemRegex + ")*";
#endif

std::string FlakeRef::to_string() const
{
    return input->to_string();
}

fetchers::Input::Attrs FlakeRef::toAttrs() const
{
    auto attrs = input->toAttrs();
    if (subdir != "")
        attrs.emplace("subdir", subdir);
    return attrs;
}

std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
{
    str << flakeRef.to_string();
    return str;
}

bool FlakeRef::operator ==(const FlakeRef & other) const
{
    return *input == *other.input && subdir == other.subdir;
}

FlakeRef FlakeRef::resolve(ref<Store> store) const
{
    return FlakeRef(lookupInRegistries(store, input), subdir);
}

FlakeRef parseFlakeRef(
    const std::string & url, const std::optional<Path> & baseDir)
{
    auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir);
    if (fragment != "")
        throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
    return flakeRef;
}

std::optional<FlakeRef> maybeParseFlakeRef(
    const std::string & url, const std::optional<Path> & baseDir)
{
    try {
        return parseFlakeRef(url, baseDir);
    } catch (Error &) {
        return {};
    }
}

std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
    const std::string & url, const std::optional<Path> & baseDir)
{
    using namespace fetchers;

    static std::regex pathUrlRegex(
        "(" + pathRegex + "/?)"
        + "(?:\\?(" + queryRegex + "))?"
        + "(?:#(" + queryRegex + "))?",
        std::regex::ECMAScript);

    static std::regex flakeRegex(
        "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)"
        + "(?:#(" + queryRegex + "))?",
        std::regex::ECMAScript);

    std::smatch match;

    /* Check if 'url' is a flake ID. This is an abbreviated syntax for
       'flake:<flake-id>?ref=<ref>&rev=<rev>'. */

    if (std::regex_match(url, match, flakeRegex)) {
        auto parsedURL = ParsedURL{
            .url = url,
            .base = "flake:" + std::string(match[1]),
            .scheme = "flake",
            .authority = "",
            .path = match[1],
            .fragment = percentDecode(std::string(match[6]))
        };

        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), ""),
            parsedURL.fragment);
    }

    /* Check if 'url' is a path (either absolute or relative to
       'baseDir'). If so, search upward to the root of the repo
       (i.e. the directory containing .git). */

    else if (std::regex_match(url, match, pathUrlRegex)) {
        std::string path = match[1];
        if (!baseDir && !hasPrefix(path, "/"))
            throw BadURL("flake reference '%s' is not an absolute path", url);
        path = absPath(path, baseDir, true);

        if (!S_ISDIR(lstat(path).st_mode))
            throw BadURL("path '%s' is not a flake (because it's not a directory)", path);

        auto flakeRoot = path;
        std::string subdir;

        while (true) {
            if (pathExists(flakeRoot + "/.git")) break;
            subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
            flakeRoot = dirOf(flakeRoot);
            if (flakeRoot == "/")
                throw BadURL("path '%s' is not a flake (because it does not reference a Git repository)", path);
        }

        auto base = std::string("git+file://") + flakeRoot;

        auto parsedURL = ParsedURL{
            .url = base, // FIXME
            .base = base,
            .scheme = "git+file",
            .authority = "",
            .path = flakeRoot,
            .query = decodeQuery(match[2]),
            .fragment = percentDecode(std::string(match[3]))
        };

        if (subdir != "") {
            if (parsedURL.query.count("subdir"))
                throw Error("flake URL '%s' has an inconsistent 'subdir' parameter", url);
            parsedURL.query.insert_or_assign("subdir", subdir);
        }

        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "subdir").value_or("")),
            parsedURL.fragment);
    }

    else {
        auto parsedURL = parseURL(url);
        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "subdir").value_or("")),
            parsedURL.fragment);
    }
}

std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
    const std::string & url, const std::optional<Path> & baseDir)
{
    try {
        return parseFlakeRefWithFragment(url, baseDir);
    } catch (Error & e) {
        return {};
    }
}

FlakeRef FlakeRef::fromAttrs(const fetchers::Input::Attrs & attrs)
{
    auto attrs2(attrs);
    attrs2.erase("subdir");
    return FlakeRef(
        fetchers::inputFromAttrs(attrs2),
        fetchers::maybeGetStrAttr(attrs, "subdir").value_or(""));
}

std::pair<fetchers::Tree, FlakeRef> FlakeRef::fetchTree(ref<Store> store) const
{
    auto [tree, lockedInput] = input->fetchTree(store);
    return {std::move(tree), FlakeRef(lockedInput, subdir)};
}

}
<commit_msg>Don't store fragment in FlakeRef<commit_after>#include "flakeref.hh"
#include "store-api.hh"
#include "fetchers/parse.hh"
#include "fetchers/fetchers.hh"
#include "fetchers/registry.hh"
#include "fetchers/regex.hh"

namespace nix {

#if 0
// 'dir' path elements cannot start with a '.'. We also reject
// potentially dangerous characters like ';'.
const static std::string subDirElemRegex = "(?:[a-zA-Z0-9_-]+[a-zA-Z0-9._-]*)";
const static std::string subDirRegex = subDirElemRegex + "(?:/" + subDirElemRegex + ")*";
#endif

std::string FlakeRef::to_string() const
{
    return input->to_string();
}

fetchers::Input::Attrs FlakeRef::toAttrs() const
{
    auto attrs = input->toAttrs();
    if (subdir != "")
        attrs.emplace("subdir", subdir);
    return attrs;
}

std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
{
    str << flakeRef.to_string();
    return str;
}

bool FlakeRef::operator ==(const FlakeRef & other) const
{
    return *input == *other.input && subdir == other.subdir;
}

FlakeRef FlakeRef::resolve(ref<Store> store) const
{
    return FlakeRef(lookupInRegistries(store, input), subdir);
}

FlakeRef parseFlakeRef(
    const std::string & url, const std::optional<Path> & baseDir)
{
    auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir);
    if (fragment != "")
        throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
    return flakeRef;
}

std::optional<FlakeRef> maybeParseFlakeRef(
    const std::string & url, const std::optional<Path> & baseDir)
{
    try {
        return parseFlakeRef(url, baseDir);
    } catch (Error &) {
        return {};
    }
}

std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
    const std::string & url, const std::optional<Path> & baseDir)
{
    using namespace fetchers;

    static std::regex pathUrlRegex(
        "(" + pathRegex + "/?)"
        + "(?:\\?(" + queryRegex + "))?"
        + "(?:#(" + queryRegex + "))?",
        std::regex::ECMAScript);

    static std::regex flakeRegex(
        "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)"
        + "(?:#(" + queryRegex + "))?",
        std::regex::ECMAScript);

    std::smatch match;

    /* Check if 'url' is a flake ID. This is an abbreviated syntax for
       'flake:<flake-id>?ref=<ref>&rev=<rev>'. */

    if (std::regex_match(url, match, flakeRegex)) {
        auto parsedURL = ParsedURL{
            .url = url,
            .base = "flake:" + std::string(match[1]),
            .scheme = "flake",
            .authority = "",
            .path = match[1],
        };

        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), ""),
            percentDecode(std::string(match[6])));
    }

    /* Check if 'url' is a path (either absolute or relative to
       'baseDir'). If so, search upward to the root of the repo
       (i.e. the directory containing .git). */

    else if (std::regex_match(url, match, pathUrlRegex)) {
        std::string path = match[1];
        if (!baseDir && !hasPrefix(path, "/"))
            throw BadURL("flake reference '%s' is not an absolute path", url);
        path = absPath(path, baseDir, true);

        if (!S_ISDIR(lstat(path).st_mode))
            throw BadURL("path '%s' is not a flake (because it's not a directory)", path);

        auto flakeRoot = path;
        std::string subdir;

        while (true) {
            if (pathExists(flakeRoot + "/.git")) break;
            subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
            flakeRoot = dirOf(flakeRoot);
            if (flakeRoot == "/")
                throw BadURL("path '%s' is not a flake (because it does not reference a Git repository)", path);
        }

        auto base = std::string("git+file://") + flakeRoot;

        auto parsedURL = ParsedURL{
            .url = base, // FIXME
            .base = base,
            .scheme = "git+file",
            .authority = "",
            .path = flakeRoot,
            .query = decodeQuery(match[2]),
        };

        auto fragment = percentDecode(std::string(match[3]));

        if (subdir != "") {
            if (parsedURL.query.count("subdir"))
                throw Error("flake URL '%s' has an inconsistent 'subdir' parameter", url);
            parsedURL.query.insert_or_assign("subdir", subdir);
        }

        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "subdir").value_or("")),
            fragment);
    }

    else {
        auto parsedURL = parseURL(url);
        std::string fragment;
        std::swap(fragment, parsedURL.fragment);
        return std::make_pair(
            FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "subdir").value_or("")),
            fragment);
    }
}

std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
    const std::string & url, const std::optional<Path> & baseDir)
{
    try {
        return parseFlakeRefWithFragment(url, baseDir);
    } catch (Error & e) {
        return {};
    }
}

FlakeRef FlakeRef::fromAttrs(const fetchers::Input::Attrs & attrs)
{
    auto attrs2(attrs);
    attrs2.erase("subdir");
    return FlakeRef(
        fetchers::inputFromAttrs(attrs2),
        fetchers::maybeGetStrAttr(attrs, "subdir").value_or(""));
}

std::pair<fetchers::Tree, FlakeRef> FlakeRef::fetchTree(ref<Store> store) const
{
    auto [tree, lockedInput] = input->fetchTree(store);
    return {std::move(tree), FlakeRef(lockedInput, subdir)};
}

}
<|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/common/chrome_content_client.h"

#include "base/command_line.h"
#include "base/string_split.h"
#include "content/public/common/content_switches.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

void CheckUserAgentStringOrdering(bool mobile_device) {
  std::vector<std::string> pieces;

  // Check if the pieces of the user agent string come in the correct order.
  chrome::ChromeContentClient content_client;
  std::string buffer = content_client.GetUserAgent();

  base::SplitStringUsingSubstr(buffer, "Mozilla/5.0 (", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  EXPECT_EQ("", pieces[0]);

  base::SplitStringUsingSubstr(buffer, ") AppleWebKit/", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  std::string os_str = pieces[0];

  base::SplitStringUsingSubstr(buffer, " (KHTML, like Gecko) ", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  std::string webkit_version_str = pieces[0];

  base::SplitStringUsingSubstr(buffer, " Safari/", &pieces);
  ASSERT_EQ(2u, pieces.size());
  std::string product_str = pieces[0];
  std::string safari_version_str = pieces[1];

  // Not sure what can be done to better check the OS string, since it's highly
  // platform-dependent.
  EXPECT_TRUE(os_str.size() > 0);

  // Check that the version numbers match.
  EXPECT_TRUE(webkit_version_str.size() > 0);
  EXPECT_TRUE(safari_version_str.size() > 0);
  EXPECT_EQ(webkit_version_str, safari_version_str);

  EXPECT_EQ(0u, product_str.find("Chrome/"));
  if (mobile_device) {
    // "Mobile" gets tacked on to the end for mobile devices, like phones.
    const std::string kMobileStr = " Mobile";
    EXPECT_EQ(kMobileStr,
              product_str.substr(product_str.size() - kMobileStr.size()));
  }
}

}  // namespace

namespace chrome_common {

TEST(ChromeContentClientTest, Basic) {
#if !defined(OS_ANDROID)
  CheckUserAgentStringOrdering(false);
#else
  // Do it once for mobile devices and once for other devices.
  const char* kArguments[] = {"chrome"};
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  command_line->Reset();
  command_line->Init(1, kArguments);
  ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  CheckUserAgentStringOrdering(false);

  command_line->AppendSwitch(switches::kUseMobileUserAgent);
  ASSERT_TRUE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  CheckUserAgentStringOrdering(true);
#endif
}

}  // namespace chrome_common
<commit_msg>Fix CommandLine usage<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/common/chrome_content_client.h"

#include "base/command_line.h"
#include "base/string_split.h"
#include "content/public/common/content_switches.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

void CheckUserAgentStringOrdering(bool mobile_device) {
  std::vector<std::string> pieces;

  // Check if the pieces of the user agent string come in the correct order.
  chrome::ChromeContentClient content_client;
  std::string buffer = content_client.GetUserAgent();

  base::SplitStringUsingSubstr(buffer, "Mozilla/5.0 (", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  EXPECT_EQ("", pieces[0]);

  base::SplitStringUsingSubstr(buffer, ") AppleWebKit/", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  std::string os_str = pieces[0];

  base::SplitStringUsingSubstr(buffer, " (KHTML, like Gecko) ", &pieces);
  ASSERT_EQ(2u, pieces.size());
  buffer = pieces[1];
  std::string webkit_version_str = pieces[0];

  base::SplitStringUsingSubstr(buffer, " Safari/", &pieces);
  ASSERT_EQ(2u, pieces.size());
  std::string product_str = pieces[0];
  std::string safari_version_str = pieces[1];

  // Not sure what can be done to better check the OS string, since it's highly
  // platform-dependent.
  EXPECT_TRUE(os_str.size() > 0);

  // Check that the version numbers match.
  EXPECT_TRUE(webkit_version_str.size() > 0);
  EXPECT_TRUE(safari_version_str.size() > 0);
  EXPECT_EQ(webkit_version_str, safari_version_str);

  EXPECT_EQ(0u, product_str.find("Chrome/"));
  if (mobile_device) {
    // "Mobile" gets tacked on to the end for mobile devices, like phones.
    const std::string kMobileStr = " Mobile";
    EXPECT_EQ(kMobileStr,
              product_str.substr(product_str.size() - kMobileStr.size()));
  }
}

}  // namespace

namespace chrome_common {

TEST(ChromeContentClientTest, Basic) {
#if !defined(OS_ANDROID)
  CheckUserAgentStringOrdering(false);
#else
  const char* kArguments[] = {"chrome"};
  CommandLine::Reset();
  CommandLine::Init(1, kArguments);
  CommandLine* command_line = CommandLine::ForCurrentProcess();

  // Do it for regular devices.
  ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  CheckUserAgentStringOrdering(false);

  // Do it for mobile devices.
  command_line->AppendSwitch(switches::kUseMobileUserAgent);
  ASSERT_TRUE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  CheckUserAgentStringOrdering(true);
#endif
}

}  // namespace chrome_common
<|endoftext|>


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

#include "chrome/common/extensions/extension_constants.h"

namespace extension_manifest_keys {

const wchar_t* kAllFrames = L"all_frames";
const wchar_t* kApp = L"app";
const wchar_t* kAppExtent = L"extent";
const wchar_t* kAppLaunchUrl = L"launch.url";
const wchar_t* kAppLaunchWindowType = L"launch.window_type";
const wchar_t* kBackground = L"background_page";
const wchar_t* kBrowserAction = L"browser_action";
const wchar_t* kChromeURLOverrides = L"chrome_url_overrides";
const wchar_t* kContentScripts = L"content_scripts";
const wchar_t* kConvertedFromUserScript = L"converted_from_user_script";
const wchar_t* kCss = L"css";
const wchar_t* kCurrentLocale = L"current_locale";
const wchar_t* kDefaultLocale = L"default_locale";
const wchar_t* kDescription = L"description";
const wchar_t* kIcons = L"icons";
const wchar_t* kJs = L"js";
const wchar_t* kMatches = L"matches";
const wchar_t* kMinimumChromeVersion = L"minimum_chrome_version";
const wchar_t* kIncludeGlobs = L"include_globs";
const wchar_t* kExcludeGlobs = L"exclude_globs";
const wchar_t* kName = L"name";
const wchar_t* kPageActionId = L"id";
const wchar_t* kPageAction = L"page_action";
const wchar_t* kPageActions = L"page_actions";
const wchar_t* kPageActionIcons = L"icons";
const wchar_t* kPageActionDefaultIcon = L"default_icon";
const wchar_t* kPageActionDefaultPopup = L"default_popup";
const wchar_t* kPageActionDefaultTitle = L"default_title";
const wchar_t* kPageActionPopup = L"popup";
const wchar_t* kPageActionPopupHeight = L"height";
const wchar_t* kPageActionPopupPath = L"path";
const wchar_t* kPermissions = L"permissions";
const wchar_t* kPlugins = L"plugins";
const wchar_t* kPluginsPath = L"path";
const wchar_t* kPluginsPublic = L"public";
const wchar_t* kPublicKey = L"key";
const wchar_t* kRunAt = L"run_at";
const wchar_t* kSignature = L"signature";
const wchar_t* kTheme = L"theme";
const wchar_t* kThemeImages = L"images";
const wchar_t* kThemeColors = L"colors";
const wchar_t* kThemeTints = L"tints";
const wchar_t* kThemeDisplayProperties = L"properties";
const wchar_t* kToolstripMoleHeight = L"mole_height";
const wchar_t* kToolstripMolePath = L"mole";
const wchar_t* kToolstripPath = L"path";
const wchar_t* kToolstrips = L"toolstrips";
const wchar_t* kType = L"type";
const wchar_t* kVersion = L"version";
const wchar_t* kUpdateURL = L"update_url";
const wchar_t* kOptionsPage = L"options_page";
}  // namespace extension_manifest_keys

namespace extension_manifest_values {
const char* kRunAtDocumentStart = "document_start";
const char* kRunAtDocumentEnd = "document_end";
const char* kRunAtDocumentIdle = "document_idle";
const char* kPageActionTypeTab = "tab";
const char* kPageActionTypePermanent = "permanent";
const char* kWindowTypeApp = "app";
const char* kWindowTypePanel = "panel";
}  // namespace extension_manifest_values

// Extension-related error messages. Some of these are simple patterns, where a
// '*' is replaced at runtime with a specific value. This is used instead of
// printf because we want to unit test them and scanf is hard to make
// cross-platform.
namespace extension_manifest_errors {
const char* kChromeVersionTooLow =
    "This extension requires * version * or greater.";
const char* kInvalidAllFrames =
    "Invalid value for 'content_scripts[*].all_frames'.";
const char* kInvalidApp = "Invalid app.";
const char* kInvalidAppExtent = "Invalid value for app.extent.";
const char* kInvalidAppExtentPattern = "Invalid value for app.extent[*].";
const char* kInvalidAppLaunchUrl =
    "Required value 'app.launch.url' is missing or invalid.";
const char* kInvalidAppLaunchWindowType =
    "Invalid value for 'app.launch.window_type'.";
const char* kInvalidBrowserAction =
    "Invalid value for 'browser_action'.";
const char* kInvalidChromeURLOverrides =
    "Invalid value for 'chrome_url_overrides'.";
const char* kInvalidContentScript =
    "Invalid value for 'content_scripts[*]'.";
const char* kInvalidContentScriptsList =
    "Invalid value for 'content_scripts'.";
const char* kInvalidCss =
    "Invalid value for 'content_scripts[*].css[*]'.";
const char* kInvalidCssList =
    "Required value 'content_scripts[*].css' is invalid.";
const char* kInvalidDescription =
    "Invalid value for 'description'.";
const char* kInvalidGlobList =
    "Invalid value for 'content_scripts[*].*'.";
const char* kInvalidGlob =
    "Invalid value for 'content_scripts[*].*[*]'.";
const char* kInvalidIcons =
    "Invalid value for 'icons'.";
const char* kInvalidIconPath =
    "Invalid value for 'icons[\"*\"]'.";
const char* kInvalidJs =
    "Invalid value for 'content_scripts[*].js[*]'.";
const char* kInvalidJsList =
    "Required value 'content_scripts[*].js' is invalid.";
const char* kInvalidKey =
    "Value 'key' is missing or invalid.";
const char* kInvalidManifest =
    "Manifest file is invalid.";
const char* kInvalidMatchCount =
    "Invalid value for 'content_scripts[*].matches'. There must be at least"
    "one match specified.";
const char* kInvalidMatch =
    "Invalid value for 'content_scripts[*].matches[*]'.";
const char* kInvalidMatches =
    "Required value 'content_scripts[*].matches' is missing or invalid.";
const char* kInvalidMinimumChromeVersion =
    "Invalid value for 'minimum_chrome_version'.";
const char* kInvalidName =
    "Required value 'name' is missing or invalid.";
const char* kInvalidPageAction =
    "Invalid value for 'page_action'.";
const char* kInvalidPageActionName =
    "Invalid value for 'page_action.name'.";
const char* kInvalidPageActionIconPath =
    "Invalid value for 'page_action.default_icon'.";
const char* kInvalidPageActionsList =
    "Invalid value for 'page_actions'.";
const char* kInvalidPageActionsListSize =
    "Invalid value for 'page_actions'. There can be at most one page action.";
const char* kInvalidPageActionId =
    "Required value 'id' is missing or invalid.";
const char* kInvalidPageActionDefaultTitle =
    "Invalid value for 'default_title'.";
const char* kInvalidPageActionOldAndNewKeys =
    "Key \"*\" is deprecated.  Key \"*\" has the same meaning.  You can not "
    "use both.";
const char* kInvalidPageActionPopup =
    "Invalid type for page action popup.";
const char* kInvalidPageActionPopupHeight =
    "Invalid value for page action popup height [*].";
const char* kInvalidPageActionPopupPath =
    "Invalid value for page action popup path [*].";
const char* kInvalidPageActionTypeValue =
    "Invalid value for 'page_actions[*].type', expected 'tab' or 'permanent'.";
const char* kInvalidPermissions =
    "Required value 'permissions' is missing or invalid.";
const char* kInvalidPermission =
    "Invalid value for 'permissions[*]'.";
const char* kInvalidPermissionScheme =
    "Invalid scheme for 'permissions[*]'. Only 'http' and 'https' are "
    "allowed.";
const char* kInvalidPlugins =
    "Invalid value for 'plugins'.";
const char* kInvalidPluginsPath =
    "Invalid value for 'plugins[*].path'.";
const char* kInvalidPluginsPublic =
    "Invalid value for 'plugins[*].public'.";
const char* kInvalidBackground =
    "Invalid value for 'background_page'.";
const char* kInvalidRunAt =
    "Invalid value for 'content_scripts[*].run_at'.";
const char* kInvalidSignature =
    "Value 'signature' is missing or invalid.";
const char* kInvalidToolstrip =
    "Invalid value for 'toolstrips[*]'";
const char* kInvalidToolstrips =
    "Invalid value for 'toolstrips'.";
const char* kInvalidVersion =
    "Required value 'version' is missing or invalid. It must be between 1-4 "
    "dot-separated integers.";
const char* kInvalidZipHash =
    "Required key 'zip_hash' is missing or invalid.";
const char* kManifestParseError =
    "Manifest is not valid JSON.";
const char* kManifestUnreadable =
    "Manifest file is missing or unreadable.";
const char* kMissingFile =
    "At least one js or css file is required for 'content_scripts[*]'.";
const char* kInvalidTheme =
    "Invalid value for 'theme'.";
const char* kInvalidThemeImages =
    "Invalid value for theme images - images must be strings.";
const char* kInvalidThemeImagesMissing =
    "Am image specified in the theme is missing.";
const char* kInvalidThemeColors =
    "Invalid value for theme colors - colors must be integers";
const char* kInvalidThemeTints =
    "Invalid value for theme images - tints must be decimal numbers.";
const char* kInvalidUpdateURL =
    "Invalid value for update url: '[*]'.";
const char* kInvalidDefaultLocale =
    "Invalid value for default locale - locale name must be a string.";
const char* kOneUISurfaceOnly =
    "An extension cannot have both a page action and a browser action.";
const char* kThemesCannotContainExtensions =
    "A theme cannot contain extensions code.";
const char* kLocalesNoDefaultLocaleSpecified =
    "Localization used, but default_locale wasn't specified in the manifest.";
const char* kLocalesNoDefaultMessages =
    "Default locale is defined but default data couldn't be loaded.";
const char* kLocalesNoValidLocaleNamesListed =
    "No valid locale name could be found in _locales directory.";
const char* kLocalesTreeMissing =
    "Default locale was specified, but _locales subtree is missing.";
const char* kLocalesMessagesFileMissing =
    "Messages file is missing for locale.";
const char* kInvalidOptionsPage =
    "Invalid value for 'options_page'.";
const char* kReservedMessageFound =
    "Reserved key * found in message catalog.";
const char* kCannotAccessPage = "Cannot access contents of url \"*\". "
    "Extension manifest must request permission to access this host.";
const char* kCannotScriptGallery = "The extensions gallery cannot be scripted.";
}  // namespace extension_manifest_errors

namespace extension_urls {
const char* kGalleryBrowsePrefix = "https://chrome.google.com/extensions";
const char* kGalleryDownloadPrefix =
    "https://clients2.googleusercontent.com/crx/download";
const char* kMiniGalleryBrowsePrefix = "https://tools.google.com/chrome/";
const char* kMiniGalleryDownloadPrefix = "https://dl-ssl.google.com/chrome/";
}
<commit_msg>Make the invalid version error a bit more specific; the previous text led me to believe each component of the version string could be a 32-bit integer.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/extensions/extension_constants.h"

namespace extension_manifest_keys {

const wchar_t* kAllFrames = L"all_frames";
const wchar_t* kApp = L"app";
const wchar_t* kAppExtent = L"extent";
const wchar_t* kAppLaunchUrl = L"launch.url";
const wchar_t* kAppLaunchWindowType = L"launch.window_type";
const wchar_t* kBackground = L"background_page";
const wchar_t* kBrowserAction = L"browser_action";
const wchar_t* kChromeURLOverrides = L"chrome_url_overrides";
const wchar_t* kContentScripts = L"content_scripts";
const wchar_t* kConvertedFromUserScript = L"converted_from_user_script";
const wchar_t* kCss = L"css";
const wchar_t* kCurrentLocale = L"current_locale";
const wchar_t* kDefaultLocale = L"default_locale";
const wchar_t* kDescription = L"description";
const wchar_t* kIcons = L"icons";
const wchar_t* kJs = L"js";
const wchar_t* kMatches = L"matches";
const wchar_t* kMinimumChromeVersion = L"minimum_chrome_version";
const wchar_t* kIncludeGlobs = L"include_globs";
const wchar_t* kExcludeGlobs = L"exclude_globs";
const wchar_t* kName = L"name";
const wchar_t* kPageActionId = L"id";
const wchar_t* kPageAction = L"page_action";
const wchar_t* kPageActions = L"page_actions";
const wchar_t* kPageActionIcons = L"icons";
const wchar_t* kPageActionDefaultIcon = L"default_icon";
const wchar_t* kPageActionDefaultPopup = L"default_popup";
const wchar_t* kPageActionDefaultTitle = L"default_title";
const wchar_t* kPageActionPopup = L"popup";
const wchar_t* kPageActionPopupHeight = L"height";
const wchar_t* kPageActionPopupPath = L"path";
const wchar_t* kPermissions = L"permissions";
const wchar_t* kPlugins = L"plugins";
const wchar_t* kPluginsPath = L"path";
const wchar_t* kPluginsPublic = L"public";
const wchar_t* kPublicKey = L"key";
const wchar_t* kRunAt = L"run_at";
const wchar_t* kSignature = L"signature";
const wchar_t* kTheme = L"theme";
const wchar_t* kThemeImages = L"images";
const wchar_t* kThemeColors = L"colors";
const wchar_t* kThemeTints = L"tints";
const wchar_t* kThemeDisplayProperties = L"properties";
const wchar_t* kToolstripMoleHeight = L"mole_height";
const wchar_t* kToolstripMolePath = L"mole";
const wchar_t* kToolstripPath = L"path";
const wchar_t* kToolstrips = L"toolstrips";
const wchar_t* kType = L"type";
const wchar_t* kVersion = L"version";
const wchar_t* kUpdateURL = L"update_url";
const wchar_t* kOptionsPage = L"options_page";
}  // namespace extension_manifest_keys

namespace extension_manifest_values {
const char* kRunAtDocumentStart = "document_start";
const char* kRunAtDocumentEnd = "document_end";
const char* kRunAtDocumentIdle = "document_idle";
const char* kPageActionTypeTab = "tab";
const char* kPageActionTypePermanent = "permanent";
const char* kWindowTypeApp = "app";
const char* kWindowTypePanel = "panel";
}  // namespace extension_manifest_values

// Extension-related error messages. Some of these are simple patterns, where a
// '*' is replaced at runtime with a specific value. This is used instead of
// printf because we want to unit test them and scanf is hard to make
// cross-platform.
namespace extension_manifest_errors {
const char* kChromeVersionTooLow =
    "This extension requires * version * or greater.";
const char* kInvalidAllFrames =
    "Invalid value for 'content_scripts[*].all_frames'.";
const char* kInvalidApp = "Invalid app.";
const char* kInvalidAppExtent = "Invalid value for app.extent.";
const char* kInvalidAppExtentPattern = "Invalid value for app.extent[*].";
const char* kInvalidAppLaunchUrl =
    "Required value 'app.launch.url' is missing or invalid.";
const char* kInvalidAppLaunchWindowType =
    "Invalid value for 'app.launch.window_type'.";
const char* kInvalidBrowserAction =
    "Invalid value for 'browser_action'.";
const char* kInvalidChromeURLOverrides =
    "Invalid value for 'chrome_url_overrides'.";
const char* kInvalidContentScript =
    "Invalid value for 'content_scripts[*]'.";
const char* kInvalidContentScriptsList =
    "Invalid value for 'content_scripts'.";
const char* kInvalidCss =
    "Invalid value for 'content_scripts[*].css[*]'.";
const char* kInvalidCssList =
    "Required value 'content_scripts[*].css' is invalid.";
const char* kInvalidDescription =
    "Invalid value for 'description'.";
const char* kInvalidGlobList =
    "Invalid value for 'content_scripts[*].*'.";
const char* kInvalidGlob =
    "Invalid value for 'content_scripts[*].*[*]'.";
const char* kInvalidIcons =
    "Invalid value for 'icons'.";
const char* kInvalidIconPath =
    "Invalid value for 'icons[\"*\"]'.";
const char* kInvalidJs =
    "Invalid value for 'content_scripts[*].js[*]'.";
const char* kInvalidJsList =
    "Required value 'content_scripts[*].js' is invalid.";
const char* kInvalidKey =
    "Value 'key' is missing or invalid.";
const char* kInvalidManifest =
    "Manifest file is invalid.";
const char* kInvalidMatchCount =
    "Invalid value for 'content_scripts[*].matches'. There must be at least"
    "one match specified.";
const char* kInvalidMatch =
    "Invalid value for 'content_scripts[*].matches[*]'.";
const char* kInvalidMatches =
    "Required value 'content_scripts[*].matches' is missing or invalid.";
const char* kInvalidMinimumChromeVersion =
    "Invalid value for 'minimum_chrome_version'.";
const char* kInvalidName =
    "Required value 'name' is missing or invalid.";
const char* kInvalidPageAction =
    "Invalid value for 'page_action'.";
const char* kInvalidPageActionName =
    "Invalid value for 'page_action.name'.";
const char* kInvalidPageActionIconPath =
    "Invalid value for 'page_action.default_icon'.";
const char* kInvalidPageActionsList =
    "Invalid value for 'page_actions'.";
const char* kInvalidPageActionsListSize =
    "Invalid value for 'page_actions'. There can be at most one page action.";
const char* kInvalidPageActionId =
    "Required value 'id' is missing or invalid.";
const char* kInvalidPageActionDefaultTitle =
    "Invalid value for 'default_title'.";
const char* kInvalidPageActionOldAndNewKeys =
    "Key \"*\" is deprecated.  Key \"*\" has the same meaning.  You can not "
    "use both.";
const char* kInvalidPageActionPopup =
    "Invalid type for page action popup.";
const char* kInvalidPageActionPopupHeight =
    "Invalid value for page action popup height [*].";
const char* kInvalidPageActionPopupPath =
    "Invalid value for page action popup path [*].";
const char* kInvalidPageActionTypeValue =
    "Invalid value for 'page_actions[*].type', expected 'tab' or 'permanent'.";
const char* kInvalidPermissions =
    "Required value 'permissions' is missing or invalid.";
const char* kInvalidPermission =
    "Invalid value for 'permissions[*]'.";
const char* kInvalidPermissionScheme =
    "Invalid scheme for 'permissions[*]'. Only 'http' and 'https' are "
    "allowed.";
const char* kInvalidPlugins =
    "Invalid value for 'plugins'.";
const char* kInvalidPluginsPath =
    "Invalid value for 'plugins[*].path'.";
const char* kInvalidPluginsPublic =
    "Invalid value for 'plugins[*].public'.";
const char* kInvalidBackground =
    "Invalid value for 'background_page'.";
const char* kInvalidRunAt =
    "Invalid value for 'content_scripts[*].run_at'.";
const char* kInvalidSignature =
    "Value 'signature' is missing or invalid.";
const char* kInvalidToolstrip =
    "Invalid value for 'toolstrips[*]'";
const char* kInvalidToolstrips =
    "Invalid value for 'toolstrips'.";
const char* kInvalidVersion =
    "Required value 'version' is missing or invalid. It must be between 1-4 "
    "dot-separated integers each between 0 and 65536.";
const char* kInvalidZipHash =
    "Required key 'zip_hash' is missing or invalid.";
const char* kManifestParseError =
    "Manifest is not valid JSON.";
const char* kManifestUnreadable =
    "Manifest file is missing or unreadable.";
const char* kMissingFile =
    "At least one js or css file is required for 'content_scripts[*]'.";
const char* kInvalidTheme =
    "Invalid value for 'theme'.";
const char* kInvalidThemeImages =
    "Invalid value for theme images - images must be strings.";
const char* kInvalidThemeImagesMissing =
    "Am image specified in the theme is missing.";
const char* kInvalidThemeColors =
    "Invalid value for theme colors - colors must be integers";
const char* kInvalidThemeTints =
    "Invalid value for theme images - tints must be decimal numbers.";
const char* kInvalidUpdateURL =
    "Invalid value for update url: '[*]'.";
const char* kInvalidDefaultLocale =
    "Invalid value for default locale - locale name must be a string.";
const char* kOneUISurfaceOnly =
    "An extension cannot have both a page action and a browser action.";
const char* kThemesCannotContainExtensions =
    "A theme cannot contain extensions code.";
const char* kLocalesNoDefaultLocaleSpecified =
    "Localization used, but default_locale wasn't specified in the manifest.";
const char* kLocalesNoDefaultMessages =
    "Default locale is defined but default data couldn't be loaded.";
const char* kLocalesNoValidLocaleNamesListed =
    "No valid locale name could be found in _locales directory.";
const char* kLocalesTreeMissing =
    "Default locale was specified, but _locales subtree is missing.";
const char* kLocalesMessagesFileMissing =
    "Messages file is missing for locale.";
const char* kInvalidOptionsPage =
    "Invalid value for 'options_page'.";
const char* kReservedMessageFound =
    "Reserved key * found in message catalog.";
const char* kCannotAccessPage = "Cannot access contents of url \"*\". "
    "Extension manifest must request permission to access this host.";
const char* kCannotScriptGallery = "The extensions gallery cannot be scripted.";
}  // namespace extension_manifest_errors

namespace extension_urls {
const char* kGalleryBrowsePrefix = "https://chrome.google.com/extensions";
const char* kGalleryDownloadPrefix =
    "https://clients2.googleusercontent.com/crx/download";
const char* kMiniGalleryBrowsePrefix = "https://tools.google.com/chrome/";
const char* kMiniGalleryDownloadPrefix = "https://dl-ssl.google.com/chrome/";
}
<|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/installer/util/google_update_settings.h"

#include <algorithm>

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/install_util.h"

using base::win::RegKey;

namespace {

bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
  if (!key.ReadValue(name, value)) {
    RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
    return hklm_key.ReadValue(name, value);
  }
  return true;
}

bool WriteGoogleUpdateStrKey(const wchar_t* const name,
                             const std::wstring& value) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  return key.WriteValue(name, value.c_str());
}

bool ClearGoogleUpdateStrKey(const wchar_t* const name) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  std::wstring value;
  if (!key.ReadValue(name, &value))
    return false;
  return key.WriteValue(name, L"");
}

bool RemoveGoogleUpdateStrKey(const wchar_t* const name) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  if (!key.ValueExists(name))
    return true;
  return key.DeleteValue(name);
}

}  // namespace.

bool GoogleUpdateSettings::GetCollectStatsConsent() {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
  DWORD value;
  if (!key.ReadValueDW(google_update::kRegUsageStatsField, &value)) {
    RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
    if (!hklm_key.ReadValueDW(google_update::kRegUsageStatsField, &value))
      return false;
  }
  return (1 == value);
}

bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) {
  DWORD value = consented? 1 : 0;
  // Writing to HKLM is only a best effort deal.
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateMediumKey();
  RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ | KEY_WRITE);
  key_hklm.WriteValue(google_update::kRegUsageStatsField, value);
  // Writing to HKCU is used both by chrome and by the crash reporter.
  reg_path = dist->GetStateKey();
  RegKey key_hkcu(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  return key_hkcu.WriteValue(google_update::kRegUsageStatsField, value);
}

bool GoogleUpdateSettings::GetMetricsId(std::wstring* metrics_id) {
  return ReadGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id);
}

bool GoogleUpdateSettings::SetMetricsId(const std::wstring& metrics_id) {
  return WriteGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id);
}

bool GoogleUpdateSettings::SetEULAConsent(bool consented) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateMediumKey();
  RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ | KEY_SET_VALUE);
  return key.WriteValue(google_update::kRegEULAAceptedField, consented? 1 : 0);
}

int GoogleUpdateSettings::GetLastRunTime() {
  std::wstring time_s;
  if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s))
    return -1;
  int64 time_i;
  if (!base::StringToInt64(time_s, &time_i))
    return -1;
  base::TimeDelta td =
      base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i);
  return td.InDays();
}

bool GoogleUpdateSettings::SetLastRunTime() {
  int64 time = base::Time::NowFromSystemTime().ToInternalValue();
  return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField,
                                 base::Int64ToString16(time));
}

bool GoogleUpdateSettings::RemoveLastRunTime() {
  return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField);
}

bool GoogleUpdateSettings::GetBrowser(std::wstring* browser) {
  return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser);
}

bool GoogleUpdateSettings::GetLanguage(std::wstring* language) {
  return ReadGoogleUpdateStrKey(google_update::kRegLangField, language);
}

bool GoogleUpdateSettings::GetBrand(std::wstring* brand) {
  return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand);
}

bool GoogleUpdateSettings::GetClient(std::wstring* client) {
  return ReadGoogleUpdateStrKey(google_update::kRegClientField, client);
}

bool GoogleUpdateSettings::SetClient(const std::wstring& client) {
  return WriteGoogleUpdateStrKey(google_update::kRegClientField, client);
}

bool GoogleUpdateSettings::GetReferral(std::wstring* referral) {
  return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral);
}

bool GoogleUpdateSettings::ClearReferral() {
  return ClearGoogleUpdateStrKey(google_update::kRegReferralField);
}

bool GoogleUpdateSettings::GetChromeChannel(bool system_install,
    std::wstring* channel) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (dist->GetChromeChannel(channel))
    return true;

  HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(root_key, reg_path.c_str(), KEY_READ);
  std::wstring update_branch;
  if (!key.ReadValue(google_update::kRegApField, &update_branch)) {
    *channel = L"unknown";
    return false;
  }

  // Map to something pithy for human consumption. There are no rules as to
  // what the ap string can contain, but generally it will contain a number
  // followed by a dash followed by the branch name (and then some random
  // suffix). We fall back on empty string in case we fail to parse.
  // Only ever return "", "unknown", "dev" or "beta".
  if (update_branch.find(L"-beta") != std::wstring::npos)
    *channel = L"beta";
  else if (update_branch.find(L"-dev") != std::wstring::npos)
    *channel = L"dev";
  else if (update_branch.empty())
    *channel = L"";
  else
    *channel = L"unknown";

  return true;
}

void GoogleUpdateSettings::UpdateDiffInstallStatus(bool system_install,
    bool incremental_install, int install_return_code,
    const std::wstring& product_guid) {
  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;

  RegKey key;
  std::wstring ap_key_value;
  std::wstring reg_key(google_update::kRegPathClientState);
  reg_key.append(L"\\");
  reg_key.append(product_guid);
  if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
      !key.ReadValue(google_update::kRegApField, &ap_key_value)) {
    VLOG(1) << "Application key not found.";
    if (!incremental_install || !install_return_code) {
      VLOG(1) << "Returning without changing application key.";
      key.Close();
      return;
    } else if (!key.Valid()) {
      reg_key.assign(google_update::kRegPathClientState);
      if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
          !key.CreateKey(product_guid.c_str(), KEY_ALL_ACCESS)) {
        LOG(ERROR) << "Failed to create application key.";
        key.Close();
        return;
      }
    }
  }

  std::wstring new_value = GetNewGoogleUpdateApKey(
      incremental_install, install_return_code, ap_key_value);
  if ((new_value.compare(ap_key_value) != 0) &&
      !key.WriteValue(google_update::kRegApField, new_value.c_str())) {
    LOG(ERROR) << "Failed to write value " << new_value
               << " to the registry field " << google_update::kRegApField;
  }
  key.Close();
}

std::wstring GoogleUpdateSettings::GetNewGoogleUpdateApKey(
    bool diff_install, int install_return_code, const std::wstring& value) {
  // Magic suffix that we need to add or remove to "ap" key value.
  const std::wstring kMagicSuffix = L"-full";

  bool has_magic_string = false;
  if ((value.length() >= kMagicSuffix.length()) &&
      (value.rfind(kMagicSuffix) == (value.length() - kMagicSuffix.length()))) {
    VLOG(1) << "Incremental installer failure key already set.";
    has_magic_string = true;
  }

  std::wstring new_value(value);
  if ((!diff_install || !install_return_code) && has_magic_string) {
    VLOG(1) << "Removing failure key from value " << value;
    new_value = value.substr(0, value.length() - kMagicSuffix.length());
  } else if ((diff_install && install_return_code) &&
             !has_magic_string) {
    VLOG(1) << "Incremental installer failed, setting failure key.";
    new_value.append(kMagicSuffix);
  }

  return new_value;
}

int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();

  // Minimum access needed is to be able to write to this key.
  RegKey reg_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE);
  if (!reg_key.Valid())
    return 0;

  HANDLE target_handle = 0;
  if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(),
                       GetCurrentProcess(), &target_handle, KEY_SET_VALUE,
                       TRUE, DUPLICATE_SAME_ACCESS)) {
    return 0;
  }
  return reinterpret_cast<int>(target_handle);
}

bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
    int handle, const std::wstring& key, const std::wstring& value) {
  HKEY reg_key = reinterpret_cast<HKEY>(reinterpret_cast<void*>(handle));
  DWORD size = static_cast<DWORD>(value.size()) * sizeof(wchar_t);
  LSTATUS status = RegSetValueEx(reg_key, key.c_str(), 0, REG_SZ,
      reinterpret_cast<const BYTE*>(value.c_str()), size);
  return status == ERROR_SUCCESS;
}

bool GoogleUpdateSettings::IsOrganic(const std::wstring& brand) {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kOrganicInstall))
    return true;

  static const wchar_t* kBrands[] = {
      L"CHFO", L"CHFT", L"CHHS", L"CHHM", L"CHMA", L"CHMB", L"CHME", L"CHMF",
      L"CHMG", L"CHMH", L"CHMI", L"CHMQ", L"CHMV", L"CHNB", L"CHNC", L"CHNG",
      L"CHNH", L"CHNI", L"CHOA", L"CHOB", L"CHOC", L"CHON", L"CHOO", L"CHOP",
      L"CHOQ", L"CHOR", L"CHOS", L"CHOT", L"CHOU", L"CHOX", L"CHOY", L"CHOZ",
      L"CHPD", L"CHPE", L"CHPF", L"CHPG", L"EUBB", L"EUBC", L"GGLA", L"GGLS"
  };
  const wchar_t** end = &kBrands[arraysize(kBrands)];
  const wchar_t** found = std::find(&kBrands[0], end, brand);
  if (found != end)
    return true;
  if (StartsWith(brand, L"EUB", true) || StartsWith(brand, L"EUC", true) ||
      StartsWith(brand, L"GGR", true))
    return true;
  return false;
}
<commit_msg>Add base::ThreadRestrictions::ScopedAllowIO allow_io;  to google_update_settings.cc until the bug is fixed BUG=62121 TEST=none Review URL: http://codereview.chromium.org/4655005<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/installer/util/google_update_settings.h"

#include <algorithm>

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/thread_restrictions.h"
#include "base/time.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/install_util.h"

using base::win::RegKey;

namespace {

bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
  // The registry functions below will end up going to disk.  Do this on another
  // thread to avoid slowing the IO thread.  http://crbug.com/62121
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
  if (!key.ReadValue(name, value)) {
    RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
    return hklm_key.ReadValue(name, value);
  }
  return true;
}

bool WriteGoogleUpdateStrKey(const wchar_t* const name,
                             const std::wstring& value) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  return key.WriteValue(name, value.c_str());
}

bool ClearGoogleUpdateStrKey(const wchar_t* const name) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  std::wstring value;
  if (!key.ReadValue(name, &value))
    return false;
  return key.WriteValue(name, L"");
}

bool RemoveGoogleUpdateStrKey(const wchar_t* const name) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  if (!key.ValueExists(name))
    return true;
  return key.DeleteValue(name);
}

}  // namespace.

bool GoogleUpdateSettings::GetCollectStatsConsent() {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
  DWORD value;
  if (!key.ReadValueDW(google_update::kRegUsageStatsField, &value)) {
    RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
    if (!hklm_key.ReadValueDW(google_update::kRegUsageStatsField, &value))
      return false;
  }
  return (1 == value);
}

bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) {
  DWORD value = consented? 1 : 0;
  // Writing to HKLM is only a best effort deal.
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateMediumKey();
  RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ | KEY_WRITE);
  key_hklm.WriteValue(google_update::kRegUsageStatsField, value);
  // Writing to HKCU is used both by chrome and by the crash reporter.
  reg_path = dist->GetStateKey();
  RegKey key_hkcu(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ | KEY_WRITE);
  return key_hkcu.WriteValue(google_update::kRegUsageStatsField, value);
}

bool GoogleUpdateSettings::GetMetricsId(std::wstring* metrics_id) {
  return ReadGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id);
}

bool GoogleUpdateSettings::SetMetricsId(const std::wstring& metrics_id) {
  return WriteGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id);
}

bool GoogleUpdateSettings::SetEULAConsent(bool consented) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateMediumKey();
  RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ | KEY_SET_VALUE);
  return key.WriteValue(google_update::kRegEULAAceptedField, consented? 1 : 0);
}

int GoogleUpdateSettings::GetLastRunTime() {
  std::wstring time_s;
  if (!ReadGoogleUpdateStrKey(google_update::kRegLastRunTimeField, &time_s))
    return -1;
  int64 time_i;
  if (!base::StringToInt64(time_s, &time_i))
    return -1;
  base::TimeDelta td =
      base::Time::NowFromSystemTime() - base::Time::FromInternalValue(time_i);
  return td.InDays();
}

bool GoogleUpdateSettings::SetLastRunTime() {
  int64 time = base::Time::NowFromSystemTime().ToInternalValue();
  return WriteGoogleUpdateStrKey(google_update::kRegLastRunTimeField,
                                 base::Int64ToString16(time));
}

bool GoogleUpdateSettings::RemoveLastRunTime() {
  return RemoveGoogleUpdateStrKey(google_update::kRegLastRunTimeField);
}

bool GoogleUpdateSettings::GetBrowser(std::wstring* browser) {
  return ReadGoogleUpdateStrKey(google_update::kRegBrowserField, browser);
}

bool GoogleUpdateSettings::GetLanguage(std::wstring* language) {
  return ReadGoogleUpdateStrKey(google_update::kRegLangField, language);
}

bool GoogleUpdateSettings::GetBrand(std::wstring* brand) {
  return ReadGoogleUpdateStrKey(google_update::kRegRLZBrandField, brand);
}

bool GoogleUpdateSettings::GetClient(std::wstring* client) {
  return ReadGoogleUpdateStrKey(google_update::kRegClientField, client);
}

bool GoogleUpdateSettings::SetClient(const std::wstring& client) {
  return WriteGoogleUpdateStrKey(google_update::kRegClientField, client);
}

bool GoogleUpdateSettings::GetReferral(std::wstring* referral) {
  return ReadGoogleUpdateStrKey(google_update::kRegReferralField, referral);
}

bool GoogleUpdateSettings::ClearReferral() {
  return ClearGoogleUpdateStrKey(google_update::kRegReferralField);
}

bool GoogleUpdateSettings::GetChromeChannel(bool system_install,
    std::wstring* channel) {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (dist->GetChromeChannel(channel))
    return true;

  HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  std::wstring reg_path = dist->GetStateKey();
  RegKey key(root_key, reg_path.c_str(), KEY_READ);
  std::wstring update_branch;
  if (!key.ReadValue(google_update::kRegApField, &update_branch)) {
    *channel = L"unknown";
    return false;
  }

  // Map to something pithy for human consumption. There are no rules as to
  // what the ap string can contain, but generally it will contain a number
  // followed by a dash followed by the branch name (and then some random
  // suffix). We fall back on empty string in case we fail to parse.
  // Only ever return "", "unknown", "dev" or "beta".
  if (update_branch.find(L"-beta") != std::wstring::npos)
    *channel = L"beta";
  else if (update_branch.find(L"-dev") != std::wstring::npos)
    *channel = L"dev";
  else if (update_branch.empty())
    *channel = L"";
  else
    *channel = L"unknown";

  return true;
}

void GoogleUpdateSettings::UpdateDiffInstallStatus(bool system_install,
    bool incremental_install, int install_return_code,
    const std::wstring& product_guid) {
  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;

  RegKey key;
  std::wstring ap_key_value;
  std::wstring reg_key(google_update::kRegPathClientState);
  reg_key.append(L"\\");
  reg_key.append(product_guid);
  if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
      !key.ReadValue(google_update::kRegApField, &ap_key_value)) {
    VLOG(1) << "Application key not found.";
    if (!incremental_install || !install_return_code) {
      VLOG(1) << "Returning without changing application key.";
      key.Close();
      return;
    } else if (!key.Valid()) {
      reg_key.assign(google_update::kRegPathClientState);
      if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
          !key.CreateKey(product_guid.c_str(), KEY_ALL_ACCESS)) {
        LOG(ERROR) << "Failed to create application key.";
        key.Close();
        return;
      }
    }
  }

  std::wstring new_value = GetNewGoogleUpdateApKey(
      incremental_install, install_return_code, ap_key_value);
  if ((new_value.compare(ap_key_value) != 0) &&
      !key.WriteValue(google_update::kRegApField, new_value.c_str())) {
    LOG(ERROR) << "Failed to write value " << new_value
               << " to the registry field " << google_update::kRegApField;
  }
  key.Close();
}

std::wstring GoogleUpdateSettings::GetNewGoogleUpdateApKey(
    bool diff_install, int install_return_code, const std::wstring& value) {
  // Magic suffix that we need to add or remove to "ap" key value.
  const std::wstring kMagicSuffix = L"-full";

  bool has_magic_string = false;
  if ((value.length() >= kMagicSuffix.length()) &&
      (value.rfind(kMagicSuffix) == (value.length() - kMagicSuffix.length()))) {
    VLOG(1) << "Incremental installer failure key already set.";
    has_magic_string = true;
  }

  std::wstring new_value(value);
  if ((!diff_install || !install_return_code) && has_magic_string) {
    VLOG(1) << "Removing failure key from value " << value;
    new_value = value.substr(0, value.length() - kMagicSuffix.length());
  } else if ((diff_install && install_return_code) &&
             !has_magic_string) {
    VLOG(1) << "Incremental installer failed, setting failure key.";
    new_value.append(kMagicSuffix);
  }

  return new_value;
}

int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring reg_path = dist->GetStateKey();

  // Minimum access needed is to be able to write to this key.
  RegKey reg_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE);
  if (!reg_key.Valid())
    return 0;

  HANDLE target_handle = 0;
  if (!DuplicateHandle(GetCurrentProcess(), reg_key.Handle(),
                       GetCurrentProcess(), &target_handle, KEY_SET_VALUE,
                       TRUE, DUPLICATE_SAME_ACCESS)) {
    return 0;
  }
  return reinterpret_cast<int>(target_handle);
}

bool GoogleUpdateSettings::WriteGoogleUpdateSystemClientKey(
    int handle, const std::wstring& key, const std::wstring& value) {
  HKEY reg_key = reinterpret_cast<HKEY>(reinterpret_cast<void*>(handle));
  DWORD size = static_cast<DWORD>(value.size()) * sizeof(wchar_t);
  LSTATUS status = RegSetValueEx(reg_key, key.c_str(), 0, REG_SZ,
      reinterpret_cast<const BYTE*>(value.c_str()), size);
  return status == ERROR_SUCCESS;
}

bool GoogleUpdateSettings::IsOrganic(const std::wstring& brand) {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kOrganicInstall))
    return true;

  static const wchar_t* kBrands[] = {
      L"CHFO", L"CHFT", L"CHHS", L"CHHM", L"CHMA", L"CHMB", L"CHME", L"CHMF",
      L"CHMG", L"CHMH", L"CHMI", L"CHMQ", L"CHMV", L"CHNB", L"CHNC", L"CHNG",
      L"CHNH", L"CHNI", L"CHOA", L"CHOB", L"CHOC", L"CHON", L"CHOO", L"CHOP",
      L"CHOQ", L"CHOR", L"CHOS", L"CHOT", L"CHOU", L"CHOX", L"CHOY", L"CHOZ",
      L"CHPD", L"CHPE", L"CHPF", L"CHPG", L"EUBB", L"EUBC", L"GGLA", L"GGLS"
  };
  const wchar_t** end = &kBrands[arraysize(kBrands)];
  const wchar_t** found = std::find(&kBrands[0], end, brand);
  if (found != end)
    return true;
  if (StartsWith(brand, L"EUB", true) || StartsWith(brand, L"EUC", true) ||
      StartsWith(brand, L"GGR", true))
    return true;
  return false;
}
<|endoftext|>


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

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/platform_thread.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"

#define NUMBER_OF_ITERATIONS 5

namespace {

// This Automated UI test opens static files in different tabs in a proxy
// browser. After all the tabs have opened, it switches between tabs, and notes
// time taken for each switch. It then prints out the times on the console,
// with the aim that the page cycler parser can interpret these numbers to
// draw graphs for page cycler Tab Switching Performance.
// Usage Flags: -enable-logging -dump-histograms-on-exit -log-level=0
class TabSwitchingUITest : public UITest {
 public:
  TabSwitchingUITest() {
    PathService::Get(base::DIR_SOURCE_ROOT, &path_prefix_);
    path_prefix_ = path_prefix_.AppendASCII("data");
    path_prefix_ = path_prefix_.AppendASCII("tab_switching");

    show_window_ = true;
  }

  void RunTabSwitchingUITest() {
    // Create a browser proxy.
    browser_proxy_ = automation()->GetBrowserWindow(0);

    // Open all the tabs.
    int initial_tab_count = 0;
    ASSERT_TRUE(browser_proxy_->GetTabCount(&initial_tab_count));
    int new_tab_count = OpenTabs();
    ASSERT_TRUE(browser_proxy_->WaitForTabCountToBecome(
        initial_tab_count + new_tab_count, 10000));

    // Switch linearly between tabs.
    browser_proxy_->ActivateTab(0);
    int final_tab_count = 0;
    ASSERT_TRUE(browser_proxy_->GetTabCount(&final_tab_count));
    for (int i = initial_tab_count; i < final_tab_count; ++i) {
      browser_proxy_->ActivateTab(i);
      ASSERT_TRUE(browser_proxy_->WaitForTabToBecomeActive(i, 10000));
    }

    // Close the browser to force a dump of log.
    bool application_closed = false;
    EXPECT_TRUE(CloseBrowser(browser_proxy_.get(), &application_closed));

    // Now open the corresponding log file and collect average and std dev from
    // the histogram stats generated for RenderWidgetHostHWND_WhiteoutDuration
    FilePath log_file_name;
    ASSERT_TRUE(PathService::Get(chrome::DIR_LOGS, &log_file_name));
    log_file_name = log_file_name.AppendASCII("chrome_debug.log");

    bool log_has_been_dumped = false;
    std::string contents;
    int max_tries = 20;
    do {
      log_has_been_dumped = file_util::ReadFileToString(log_file_name,
                                                        &contents);
      if (!log_has_been_dumped)
        PlatformThread::Sleep(100);
    } while (!log_has_been_dumped && max_tries--);
    ASSERT_TRUE(log_has_been_dumped) << "Failed to read the log file";

    // Parse the contents to get average and std deviation.
    std::string average("0.0"), std_dev("0.0");
    const std::string average_str("average = ");
    const std::string std_dev_str("standard deviation = ");
    std::string::size_type pos = contents.find(
        "Histogram: MPArch.RWHH_WhiteoutDuration", 0);
    std::string::size_type comma_pos;
    std::string::size_type number_length;
    if (pos != std::string::npos) {
      // Get the average.
      pos = contents.find(average_str, pos);
      comma_pos = contents.find(",", pos);
      pos += average_str.length();
      number_length = comma_pos - pos;
      average = contents.substr(pos, number_length);

      // Get the std dev.
      pos = contents.find(std_dev_str, pos);
      pos += std_dev_str.length();
      comma_pos = contents.find(" ", pos);
      number_length = comma_pos - pos;
      std_dev = contents.substr(pos, number_length);
    } else {
      LOG(WARNING) << "Histogram: MPArch.RWHH_WhiteoutDuration wasn't found";
    }

    // Print the average and standard deviation.
    PrintResultMeanAndError("tab_switch", "", "t",
                            average + ", " + std_dev, "ms",
                            true /* important */);
  }

 protected:
  // Opens new tabs. Returns the number of tabs opened.
  int OpenTabs() {
    // Add tabs.
    static const char* files[] = { "espn.go.com", "bugzilla.mozilla.org",
                                   "news.cnet.com", "www.amazon.com",
                                   "kannada.chakradeo.net", "allegro.pl",
                                   "ml.wikipedia.org", "www.bbc.co.uk",
                                   "126.com", "www.altavista.com"};
    int number_of_new_tabs_opened = 0;
    FilePath file_name;
    for (size_t i = 0; i < arraysize(files); ++i) {
      file_name = path_prefix_;
      file_name = file_name.AppendASCII(files[i]);
      file_name = file_name.AppendASCII("index.html");
      browser_proxy_->AppendTab(net::FilePathToFileURL(file_name));
      number_of_new_tabs_opened++;
    }

    return number_of_new_tabs_opened;
  }

  FilePath path_prefix_;
  scoped_refptr<BrowserProxy> browser_proxy_;

 private:
  DISALLOW_COPY_AND_ASSIGN(TabSwitchingUITest);
};

TEST_F(TabSwitchingUITest, GenerateTabSwitchStats) {
  RunTabSwitchingUITest();
}

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

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/platform_thread.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"

#define NUMBER_OF_ITERATIONS 5

namespace {

// This Automated UI test opens static files in different tabs in a proxy
// browser. After all the tabs have opened, it switches between tabs, and notes
// time taken for each switch. It then prints out the times on the console,
// with the aim that the page cycler parser can interpret these numbers to
// draw graphs for page cycler Tab Switching Performance.
// Usage Flags: --enable-logging --dump-histograms-on-exit --log-level=0
class TabSwitchingUITest : public UITest {
 public:
  TabSwitchingUITest() {
    PathService::Get(base::DIR_SOURCE_ROOT, &path_prefix_);
    path_prefix_ = path_prefix_.AppendASCII("data");
    path_prefix_ = path_prefix_.AppendASCII("tab_switching");

    show_window_ = true;
  }

  void RunTabSwitchingUITest() {
    // Create a browser proxy.
    browser_proxy_ = automation()->GetBrowserWindow(0);

    // Open all the tabs.
    int initial_tab_count = 0;
    ASSERT_TRUE(browser_proxy_->GetTabCount(&initial_tab_count));
    int new_tab_count = OpenTabs();
    ASSERT_TRUE(browser_proxy_->WaitForTabCountToBecome(
        initial_tab_count + new_tab_count, 10000));

    // Switch linearly between tabs.
    browser_proxy_->ActivateTab(0);
    int final_tab_count = 0;
    ASSERT_TRUE(browser_proxy_->GetTabCount(&final_tab_count));
    for (int i = initial_tab_count; i < final_tab_count; ++i) {
      browser_proxy_->ActivateTab(i);
      ASSERT_TRUE(browser_proxy_->WaitForTabToBecomeActive(i, 10000));
    }

    // Close the browser to force a dump of log.
    bool application_closed = false;
    EXPECT_TRUE(CloseBrowser(browser_proxy_.get(), &application_closed));

    // Now open the corresponding log file and collect average and std dev from
    // the histogram stats generated for RenderWidgetHost_TabSwitchPaintDuration
    FilePath log_file_name;
    ASSERT_TRUE(PathService::Get(chrome::DIR_LOGS, &log_file_name));
    log_file_name = log_file_name.AppendASCII("chrome_debug.log");

    bool log_has_been_dumped = false;
    std::string contents;
    int max_tries = 20;
    do {
      log_has_been_dumped = file_util::ReadFileToString(log_file_name,
                                                        &contents);
      if (!log_has_been_dumped)
        PlatformThread::Sleep(100);
    } while (!log_has_been_dumped && max_tries--);
    ASSERT_TRUE(log_has_been_dumped) << "Failed to read the log file";

    // Parse the contents to get average and std deviation.
    std::string average("0.0"), std_dev("0.0");
    const std::string average_str("average = ");
    const std::string std_dev_str("standard deviation = ");
    std::string::size_type pos = contents.find(
        "Histogram: MPArch.RWH_TabSwitchPaintDuration", 0);
    std::string::size_type comma_pos;
    std::string::size_type number_length;

    ASSERT_NE(pos, std::string::npos) <<
      "Histogram: MPArch.RWH_TabSwitchPaintDuration wasn't found\n" <<
      contents;

    // Get the average.
    pos = contents.find(average_str, pos);
    comma_pos = contents.find(",", pos);
    pos += average_str.length();
    number_length = comma_pos - pos;
    average = contents.substr(pos, number_length);

    // Get the std dev.
    pos = contents.find(std_dev_str, pos);
    pos += std_dev_str.length();
    comma_pos = contents.find(" ", pos);
    number_length = comma_pos - pos;
    std_dev = contents.substr(pos, number_length);

    // Print the average and standard deviation.
    PrintResultMeanAndError("tab_switch", "", "t",
                            average + ", " + std_dev, "ms",
                            true /* important */);
  }

 protected:
  // Opens new tabs. Returns the number of tabs opened.
  int OpenTabs() {
    // Add tabs.
    static const char* files[] = { "espn.go.com", "bugzilla.mozilla.org",
                                   "news.cnet.com", "www.amazon.com",
                                   "kannada.chakradeo.net", "allegro.pl",
                                   "ml.wikipedia.org", "www.bbc.co.uk",
                                   "126.com", "www.altavista.com"};
    int number_of_new_tabs_opened = 0;
    FilePath file_name;
    for (size_t i = 0; i < arraysize(files); ++i) {
      file_name = path_prefix_;
      file_name = file_name.AppendASCII(files[i]);
      file_name = file_name.AppendASCII("index.html");
      browser_proxy_->AppendTab(net::FilePathToFileURL(file_name));
      number_of_new_tabs_opened++;
    }

    return number_of_new_tabs_opened;
  }

  FilePath path_prefix_;
  scoped_refptr<BrowserProxy> browser_proxy_;

 private:
  DISALLOW_COPY_AND_ASSIGN(TabSwitchingUITest);
};

TEST_F(TabSwitchingUITest, GenerateTabSwitchStats) {
  RunTabSwitchingUITest();
}

}  // namespace
<|endoftext|>