<commit_before>
#ifndef WNT

#include <Standard_NullObject.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Failure.hxx>
#include <Standard_Mutex.hxx>
#include <OSD_Environment.ixx>
#include <OSD_WhoAmI.hxx>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <errno.h>

static const OSD_WhoAmI Iam = OSD_WEnvironment;

// ----------------------------------------------------------------------
//
// Updated by : JPT Dec,7 1992
// What       : OSD_Environment::OSD_Environment
//                              (const TCollection_AsciiString& Name,
//                               const TCollection_AsciiString& Value)
//              Value could contain the character $ (Ex setenv a = $c)
//
// ----------------------------------------------------------------------
// Create object

OSD_Environment::OSD_Environment()
{
}

// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------

OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name)
{

 if (!Name.IsAscii() || Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");

 myName = Name;
}

// ----------------------------------------------------------------------
// Create an environment variable and initialize it
// ----------------------------------------------------------------------

OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name,
                                 const TCollection_AsciiString& Value)
{

 if (!Name.IsAscii() || !Value.IsAscii() ||
// JPT : Dec-7-1992     Name.Search("$") != -1 || Value.Search("$") != -1)
     Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");

 myName = Name;
 myValue = Value;
}

// ----------------------------------------------------------------------
// Returns the name of the symbol
// ----------------------------------------------------------------------

TCollection_AsciiString OSD_Environment::Name () const
{
 return myName;
}

// ----------------------------------------------------------------------
// Set new value for environment variable
// ----------------------------------------------------------------------

void OSD_Environment::SetName (const TCollection_AsciiString& Name)
{
 myError.Reset();
 if (!Name.IsAscii() || Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::SetName: bad argument");

 myName = Name;
}

// ----------------------------------------------------------------------
// Change value
// ----------------------------------------------------------------------

void OSD_Environment::SetValue (const TCollection_AsciiString& Value)
{
 if (!Value.IsAscii() || Value.Search("$") != -1)
   Standard_ConstructionError::Raise("OSD_Environment::Change: bad argument");

 myValue = Value;
}

// ----------------------------------------------------------------------
// Get environment variable physically
// ----------------------------------------------------------------------

TCollection_AsciiString OSD_Environment::Value()
{
 char *result = getenv(myName.ToCString());
 if (result == NULL) myValue.Clear();
 else myValue = result;
 return myValue;
}

// ----------------------------------------------------------------------
// Sets physically the environment variable
// ----------------------------------------------------------------------

void OSD_Environment::Build ()
{
  // Static buffer to hold definitions of new variables for the environment.
  // Note that they need to be static since putenv does not make a copy
  // of the string, but just adds its pointer to the environment.
  static char **buffer  = 0 ;     // JPT:
  static int    Ibuffer = 0 ;     // Tout ca pour putenv,getenv

  // Use mutex to avoid concurrent access to the buffer
  static Standard_Mutex theMutex;
  Standard_Mutex::Sentry aSentry ( theMutex );

  // check if such variable has already been created in the buffer
  int index = -1, len = myName.Length();
  for ( int i=0; i < Ibuffer; i++ ) {
    if ( ! strncmp ( buffer[i], myName.ToCString(), len ) && buffer[i][len] == '=' ) {
      index = i;
      break;
    }
  }

  // and either add a new entry, or remember the old entry for a while
  char *old_value = 0;
  if ( index >=0 ) {
    old_value = buffer[index];
  }
  else {
    // Allocation memoire. Surtout tout la heap!
    index = Ibuffer++;
    buffer = (char **) realloc ( buffer, Ibuffer * sizeof(char*) );
  }

  // create a new entry in the buffer and add it to environment
  buffer[index] = (char *) malloc ( len + myValue.Length() + 2 );
  sprintf(buffer[index], "%s=%s", myName.ToCString(), myValue.ToCString());
  putenv(buffer[index]);

  // then (and only then!) free old entry, if existed
  if ( old_value )
    free ( old_value );

  // check the result
  char *result = getenv(myName.ToCString());
  if (result == NULL)
    myError.SetValue(errno, Iam, "Set Environment");
}

// ----------------------------------------------------------------------
// Remove physically the environment variable
// ----------------------------------------------------------------------

void OSD_Environment::Remove ()
{
  myValue.Clear();
  Build();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void OSD_Environment::Reset()
{
  myError.Reset();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
Standard_Boolean OSD_Environment::Failed() const
{
  return myError.Failed();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void OSD_Environment::Perror()
{
  myError.Perror();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
Standard_Integer OSD_Environment::Error() const
{
  return myError.Error();
}

#else

//------------------------------------------------------------------------
//-------------------  WNT Sources of OSD_Environment --------------------
//------------------------------------------------------------------------

#define STRICT
#include <OSD_Environment.hxx>

#include <OSD_WNT.hxx>

#include <windows.h>

#include <stdio.h>

#ifdef _MSC_VER
#pragma warning( disable : 4700 )
#endif

static void __fastcall _set_error ( OSD_Error&, DWORD );

OSD_Environment :: OSD_Environment () {

}  // end constructor ( 1 )

OSD_Environment :: OSD_Environment ( const TCollection_AsciiString& Name ) {

 myName = Name;

}  // end constructor ( 2 )

OSD_Environment :: OSD_Environment (
                    const TCollection_AsciiString& Name,
                    const TCollection_AsciiString& Value
                   ) {

 myName  = Name;
 myValue = Value;

}  // end constructor ( 3 )

void OSD_Environment :: SetValue ( const TCollection_AsciiString& Value ) {

 myValue = Value;

}  // end OSD_Environment :: SetValue

TCollection_AsciiString OSD_Environment :: Value () {

 Standard_PCharacter pBuff;
 DWORD            dwSize = 0;
 char*            envVal = NULL;

 myValue.Clear ();

 SetLastError ( ERROR_SUCCESS );
 dwSize = GetEnvironmentVariable (  myName.ToCString (), pBuff, dwSize  );

 if (    ( dwSize == 0 && GetLastError () != ERROR_SUCCESS ) ||
         (  envVal = getenv (  myName.ToCString ()  )  ) == NULL
 )

  _set_error ( myError, ERROR_ENVVAR_NOT_FOUND );

 else if ( envVal != NULL )

  myValue = envVal;

 else {

  ++dwSize;
  pBuff = new Standard_Character[ dwSize ];
  GetEnvironmentVariable (  (char *)myName.ToCString (), pBuff, dwSize  );
  myValue = pBuff;
  delete [] pBuff;
  Reset ();

 }  // end else

 return myValue;

}  // end OSD_Environment :: Value

void OSD_Environment :: SetName ( const TCollection_AsciiString& name ) {

 myName = name;

}  // end OSD_Environment :: SetName

TCollection_AsciiString OSD_Environment :: Name () const {

 return myName;

}  // end OSD_Environment :: Name

void OSD_Environment :: Build () {

 TCollection_AsciiString str;

 str = myName + TEXT( "=" ) + myValue;

 putenv (  str.ToCString ()  );

}  // end OSD_Environment :: Build

void OSD_Environment :: Remove () {

 TCollection_AsciiString str;

 str = myName + TEXT( "=" );

 putenv (  str.ToCString ()  );

}  // end OSD_Environment :: Remove

Standard_Boolean OSD_Environment :: Failed () const {

 return myError.Failed ();

}  // end OSD_Environment :: Failed

void OSD_Environment :: Reset () {

 myError.Reset ();

}  // end OSD_Environment :: Reset

void OSD_Environment :: Perror () {

 if (  ErrorPrefix ()  )

  (  *ErrorStream ()  ) << TEXT( '\'' ) << myName.ToCString () << TEXT( "' - " );

 myError.Perror ();

}  // end OSD_Environment :: Perror

Standard_Integer OSD_Environment :: Error () const {

 return myError.Error ();

}  // end OSD_Environment :: Error

static void __fastcall _set_error ( OSD_Error& err, DWORD code ) {

 DWORD              errCode;
 Standard_Character buffer[ 2048 ];

 errCode = code ? code : GetLastError ();

 if (  !FormatMessage (
         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
         0, errCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
         buffer, 2048, NULL
        )
 ) {

  sprintf ( buffer, "error code %d", (Standard_Integer)errCode );
  SetLastError ( errCode );

 }  // end if

 err.SetValue ( errCode, OSD_WEnvironment, buffer );

}  // end _set_error

#endif
<commit_msg>[warning-fix][uninitialized-var]<commit_after>
#ifndef WNT

#include <Standard_NullObject.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Failure.hxx>
#include <Standard_Mutex.hxx>
#include <OSD_Environment.ixx>
#include <OSD_WhoAmI.hxx>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <errno.h>

static const OSD_WhoAmI Iam = OSD_WEnvironment;

// ----------------------------------------------------------------------
//
// Updated by : JPT Dec,7 1992
// What       : OSD_Environment::OSD_Environment
//                              (const TCollection_AsciiString& Name,
//                               const TCollection_AsciiString& Value)
//              Value could contain the character $ (Ex setenv a = $c)
//
// ----------------------------------------------------------------------
// Create object

OSD_Environment::OSD_Environment()
{
}

// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------

OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name)
{

 if (!Name.IsAscii() || Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");

 myName = Name;
}

// ----------------------------------------------------------------------
// Create an environment variable and initialize it
// ----------------------------------------------------------------------

OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name,
                                 const TCollection_AsciiString& Value)
{

 if (!Name.IsAscii() || !Value.IsAscii() ||
// JPT : Dec-7-1992     Name.Search("$") != -1 || Value.Search("$") != -1)
     Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");

 myName = Name;
 myValue = Value;
}

// ----------------------------------------------------------------------
// Returns the name of the symbol
// ----------------------------------------------------------------------

TCollection_AsciiString OSD_Environment::Name () const
{
 return myName;
}

// ----------------------------------------------------------------------
// Set new value for environment variable
// ----------------------------------------------------------------------

void OSD_Environment::SetName (const TCollection_AsciiString& Name)
{
 myError.Reset();
 if (!Name.IsAscii() || Name.Search("$") != -1 )
   Standard_ConstructionError::Raise("OSD_Environment::SetName: bad argument");

 myName = Name;
}

// ----------------------------------------------------------------------
// Change value
// ----------------------------------------------------------------------

void OSD_Environment::SetValue (const TCollection_AsciiString& Value)
{
 if (!Value.IsAscii() || Value.Search("$") != -1)
   Standard_ConstructionError::Raise("OSD_Environment::Change: bad argument");

 myValue = Value;
}

// ----------------------------------------------------------------------
// Get environment variable physically
// ----------------------------------------------------------------------

TCollection_AsciiString OSD_Environment::Value()
{
 char *result = getenv(myName.ToCString());
 if (result == NULL) myValue.Clear();
 else myValue = result;
 return myValue;
}

// ----------------------------------------------------------------------
// Sets physically the environment variable
// ----------------------------------------------------------------------

void OSD_Environment::Build ()
{
  // Static buffer to hold definitions of new variables for the environment.
  // Note that they need to be static since putenv does not make a copy
  // of the string, but just adds its pointer to the environment.
  static char **buffer  = 0 ;     // JPT:
  static int    Ibuffer = 0 ;     // Tout ca pour putenv,getenv

  // Use mutex to avoid concurrent access to the buffer
  static Standard_Mutex theMutex;
  Standard_Mutex::Sentry aSentry ( theMutex );

  // check if such variable has already been created in the buffer
  int index = -1, len = myName.Length();
  for ( int i=0; i < Ibuffer; i++ ) {
    if ( ! strncmp ( buffer[i], myName.ToCString(), len ) && buffer[i][len] == '=' ) {
      index = i;
      break;
    }
  }

  // and either add a new entry, or remember the old entry for a while
  char *old_value = 0;
  if ( index >=0 ) {
    old_value = buffer[index];
  }
  else {
    // Allocation memoire. Surtout tout la heap!
    index = Ibuffer++;
    buffer = (char **) realloc ( buffer, Ibuffer * sizeof(char*) );
  }

  // create a new entry in the buffer and add it to environment
  buffer[index] = (char *) malloc ( len + myValue.Length() + 2 );
  sprintf(buffer[index], "%s=%s", myName.ToCString(), myValue.ToCString());
  putenv(buffer[index]);

  // then (and only then!) free old entry, if existed
  if ( old_value )
    free ( old_value );

  // check the result
  char *result = getenv(myName.ToCString());
  if (result == NULL)
    myError.SetValue(errno, Iam, "Set Environment");
}

// ----------------------------------------------------------------------
// Remove physically the environment variable
// ----------------------------------------------------------------------

void OSD_Environment::Remove ()
{
  myValue.Clear();
  Build();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void OSD_Environment::Reset()
{
  myError.Reset();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
Standard_Boolean OSD_Environment::Failed() const
{
  return myError.Failed();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void OSD_Environment::Perror()
{
  myError.Perror();
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
Standard_Integer OSD_Environment::Error() const
{
  return myError.Error();
}

#else

//------------------------------------------------------------------------
//-------------------  WNT Sources of OSD_Environment --------------------
//------------------------------------------------------------------------

#define STRICT
#include <OSD_Environment.hxx>

#include <OSD_WNT.hxx>

#include <windows.h>

#include <stdio.h>

#ifdef _MSC_VER
#pragma warning( disable : 4700 )
#endif

static void __fastcall _set_error ( OSD_Error&, DWORD );

OSD_Environment :: OSD_Environment () {

}  // end constructor ( 1 )

OSD_Environment :: OSD_Environment ( const TCollection_AsciiString& Name ) {

 myName = Name;

}  // end constructor ( 2 )

OSD_Environment :: OSD_Environment (
                    const TCollection_AsciiString& Name,
                    const TCollection_AsciiString& Value
                   ) {

 myName  = Name;
 myValue = Value;

}  // end constructor ( 3 )

void OSD_Environment :: SetValue ( const TCollection_AsciiString& Value ) {

 myValue = Value;

}  // end OSD_Environment :: SetValue

TCollection_AsciiString OSD_Environment :: Value () {

 Standard_PCharacter pBuff = NULL;
 DWORD            dwSize = 0;
 char*            envVal = NULL;

 myValue.Clear ();

 SetLastError ( ERROR_SUCCESS );
 dwSize = GetEnvironmentVariable (  myName.ToCString (), pBuff, dwSize  );

 if (    ( dwSize == 0 && GetLastError () != ERROR_SUCCESS ) ||
         (  envVal = getenv (  myName.ToCString ()  )  ) == NULL
 )

  _set_error ( myError, ERROR_ENVVAR_NOT_FOUND );

 else if ( envVal != NULL )

  myValue = envVal;

 else {

  ++dwSize;
  pBuff = new Standard_Character[ dwSize ];
  GetEnvironmentVariable (  (char *)myName.ToCString (), pBuff, dwSize  );
  myValue = pBuff;
  delete [] pBuff;
  Reset ();

 }  // end else

 return myValue;

}  // end OSD_Environment :: Value

void OSD_Environment :: SetName ( const TCollection_AsciiString& name ) {

 myName = name;

}  // end OSD_Environment :: SetName

TCollection_AsciiString OSD_Environment :: Name () const {

 return myName;

}  // end OSD_Environment :: Name

void OSD_Environment :: Build () {

 TCollection_AsciiString str;

 str = myName + TEXT( "=" ) + myValue;

 putenv (  str.ToCString ()  );

}  // end OSD_Environment :: Build

void OSD_Environment :: Remove () {

 TCollection_AsciiString str;

 str = myName + TEXT( "=" );

 putenv (  str.ToCString ()  );

}  // end OSD_Environment :: Remove

Standard_Boolean OSD_Environment :: Failed () const {

 return myError.Failed ();

}  // end OSD_Environment :: Failed

void OSD_Environment :: Reset () {

 myError.Reset ();

}  // end OSD_Environment :: Reset

void OSD_Environment :: Perror () {

 if (  ErrorPrefix ()  )

  (  *ErrorStream ()  ) << TEXT( '\'' ) << myName.ToCString () << TEXT( "' - " );

 myError.Perror ();

}  // end OSD_Environment :: Perror

Standard_Integer OSD_Environment :: Error () const {

 return myError.Error ();

}  // end OSD_Environment :: Error

static void __fastcall _set_error ( OSD_Error& err, DWORD code ) {

 DWORD              errCode;
 Standard_Character buffer[ 2048 ];

 errCode = code ? code : GetLastError ();

 if (  !FormatMessage (
         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
         0, errCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
         buffer, 2048, NULL
        )
 ) {

  sprintf ( buffer, "error code %d", (Standard_Integer)errCode );
  SetLastError ( errCode );

 }  // end if

 err.SetValue ( errCode, OSD_WEnvironment, buffer );

}  // end _set_error

#endif
<|endoftext|>


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

#include "chrome/browser/in_process_webkit/dom_storage_context.h"

#include <algorithm>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_util.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/in_process_webkit/dom_storage_area.h"
#include "chrome/browser/in_process_webkit/dom_storage_namespace.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/common/dom_storage_common.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "webkit/glue/webkit_glue.h"

const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] =
    FILE_PATH_LITERAL("Local Storage");

const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
    FILE_PATH_LITERAL(".localstorage");

static const FilePath::CharType kLocalStorageOldPath[] =
    FILE_PATH_LITERAL("localStorage");

// TODO(jorlow): Remove after Chrome 4 ships.
static void MigrateLocalStorageDirectory(const FilePath& data_path) {
  FilePath new_path = data_path.Append(
      DOMStorageContext::kLocalStorageDirectory);
  FilePath old_path = data_path.Append(kLocalStorageOldPath);
  if (!file_util::DirectoryExists(new_path) &&
      file_util::DirectoryExists(old_path)) {
    file_util::Move(old_path, new_path);
  }
}

DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context)
    : last_storage_area_id_(0),
      last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId),
      last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId),
      webkit_context_(webkit_context) {
}

DOMStorageContext::~DOMStorageContext() {
  // This should not go away until all DOM Storage Dispatcher hosts have gone
  // away.  And they remove themselves from this list.
  DCHECK(dispatcher_host_set_.empty());

  for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin());
       iter != storage_namespace_map_.end(); ++iter) {
    delete iter->second;
  }
}

int64 DOMStorageContext::AllocateStorageAreaId() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  return ++last_storage_area_id_;
}

int64 DOMStorageContext::AllocateSessionStorageNamespaceId() {
  if (BrowserThread::CurrentlyOn(BrowserThread::UI))
    return ++last_session_storage_namespace_id_on_ui_thread_;
  return --last_session_storage_namespace_id_on_io_thread_;
}

int64 DOMStorageContext::CloneSessionStorage(int64 original_id) {
  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 clone_id = AllocateSessionStorageNamespaceId();
  BrowserThread::PostTask(
      BrowserThread::WEBKIT, FROM_HERE, NewRunnableFunction(
          &DOMStorageContext::CompleteCloningSessionStorage,
          this, original_id, clone_id));
  return clone_id;
}

void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(!GetStorageArea(id));
  storage_area_map_[id] = storage_area;
}

void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(GetStorageArea(id));
  storage_area_map_.erase(id);
}

DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageAreaMap::iterator iter = storage_area_map_.find(id);
  if (iter == storage_area_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::DeleteSessionStorageNamespace(int64 namespace_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageNamespaceMap::iterator iter =
      storage_namespace_map_.find(namespace_id);
  if (iter == storage_namespace_map_.end())
    return;
  DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION);
  delete iter->second;
  storage_namespace_map_.erase(iter);
}

DOMStorageNamespace* DOMStorageContext::GetStorageNamespace(
    int64 id, bool allocation_allowed) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
  if (iter != storage_namespace_map_.end())
    return iter->second;
  if (!allocation_allowed)
    return NULL;
  if (id == kLocalStorageNamespaceId)
    return CreateLocalStorage();
  return CreateSessionStorage(id);
}

void DOMStorageContext::RegisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) ==
         dispatcher_host_set_.end());
  dispatcher_host_set_.insert(dispatcher_host);
}

void DOMStorageContext::UnregisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) !=
         dispatcher_host_set_.end());
  dispatcher_host_set_.erase(dispatcher_host);
}

const DOMStorageContext::DispatcherHostSet*
DOMStorageContext::GetDispatcherHostSet() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  return &dispatcher_host_set_;
}

void DOMStorageContext::PurgeMemory() {
  // It is only safe to purge the memory from the LocalStorage namespace,
  // because it is backed by disk and can be reloaded later.  If we purge a
  // SessionStorage namespace, its data will be gone forever, because it isn't
  // currently backed by disk.
  DOMStorageNamespace* local_storage =
      GetStorageNamespace(kLocalStorageNamespaceId, false);
  if (local_storage)
    local_storage->PurgeMemory();
}

void DOMStorageContext::DeleteDataModifiedSince(
    const base::Time& cutoff,
    const char* url_scheme_to_be_skipped,
    const std::vector<string16>& protected_origins) {
  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  PurgeMemory();

  file_util::FileEnumerator file_enumerator(
      webkit_context_->data_path().Append(kLocalStorageDirectory), false,
      file_util::FileEnumerator::FILES);
  for (FilePath path = file_enumerator.Next(); !path.value().empty();
       path = file_enumerator.Next()) {
    WebKit::WebSecurityOrigin web_security_origin =
        WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
            webkit_glue::FilePathToWebString(path.BaseName()));
    if (EqualsASCII(web_security_origin.protocol(), url_scheme_to_be_skipped))
      continue;

    std::vector<string16>::const_iterator find_iter =
        std::find(protected_origins.begin(), protected_origins.end(),
            web_security_origin.databaseIdentifier());
    if (find_iter != protected_origins.end())
      continue;

    file_util::FileEnumerator::FindInfo find_info;
    file_enumerator.GetFindInfo(&find_info);
    if (file_util::HasFileBeenModifiedSince(find_info, cutoff))
      file_util::Delete(path, false);
  }
}

void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));

  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  // TODO(bulach): both this method and DeleteDataModifiedSince could purge
  // only the memory used by the specific file instead of all memory at once.
  // See http://crbug.com/32000
  PurgeMemory();
  file_util::Delete(file_path, false);
}

void DOMStorageContext::DeleteLocalStorageForOrigin(const string16& origin_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  DeleteLocalStorageFile(GetLocalStorageFilePath(origin_id));
}

void DOMStorageContext::DeleteAllLocalStorageFiles() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));

  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  PurgeMemory();

  file_util::FileEnumerator file_enumerator(
      webkit_context_->data_path().Append(kLocalStorageDirectory), false,
      file_util::FileEnumerator::FILES);
  for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    if (file_path.Extension() == kLocalStorageExtension)
      file_util::Delete(file_path, false);
  }
}

DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
  FilePath data_path = webkit_context_->data_path();
  FilePath dir_path;
  if (!data_path.empty()) {
    MigrateLocalStorageDirectory(data_path);
    dir_path = data_path.Append(kLocalStorageDirectory);
  }
  DOMStorageNamespace* new_namespace =
      DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
  RegisterStorageNamespace(new_namespace);
  return new_namespace;
}

DOMStorageNamespace* DOMStorageContext::CreateSessionStorage(
    int64 namespace_id) {
  DOMStorageNamespace* new_namespace =
      DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id);
  RegisterStorageNamespace(new_namespace);
  return new_namespace;
}

void DOMStorageContext::RegisterStorageNamespace(
    DOMStorageNamespace* storage_namespace) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(!GetStorageNamespace(id, false));
  storage_namespace_map_[id] = storage_namespace;
}

/* static */
void DOMStorageContext::CompleteCloningSessionStorage(
    DOMStorageContext* context, int64 existing_id, int64 clone_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  DOMStorageNamespace* existing_namespace =
      context->GetStorageNamespace(existing_id, false);
  // If nothing exists, then there's nothing to clone.
  if (existing_namespace)
    context->RegisterStorageNamespace(existing_namespace->Copy(clone_id));
}

// static
void DOMStorageContext::ClearLocalState(const FilePath& profile_path,
                                        const char* url_scheme_to_be_skipped) {
  file_util::FileEnumerator file_enumerator(profile_path.Append(
      kLocalStorageDirectory), false, file_util::FileEnumerator::FILES);
  for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    if (file_path.Extension() == kLocalStorageExtension) {
      WebKit::WebSecurityOrigin web_security_origin =
          WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
              webkit_glue::FilePathToWebString(file_path.BaseName()));
      if (!EqualsASCII(web_security_origin.protocol(),
                       url_scheme_to_be_skipped))
        file_util::Delete(file_path, false);
    }
  }
}

FilePath DOMStorageContext::GetLocalStorageFilePath(
    const string16& origin_id) const {
  FilePath storageDir = webkit_context_->data_path().Append(
      DOMStorageContext::kLocalStorageDirectory);
  FilePath::StringType id =
      webkit_glue::WebStringToFilePathString(origin_id);
  return storageDir.Append(id.append(kLocalStorageExtension));
}
<commit_msg>Coding style clean up of DomStorageContext.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/in_process_webkit/dom_storage_context.h"

#include <algorithm>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_util.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/in_process_webkit/dom_storage_area.h"
#include "chrome/browser/in_process_webkit/dom_storage_namespace.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/common/dom_storage_common.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "webkit/glue/webkit_glue.h"

using WebKit::WebSecurityOrigin;

const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] =
    FILE_PATH_LITERAL("Local Storage");

const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
    FILE_PATH_LITERAL(".localstorage");

static const FilePath::CharType kLocalStorageOldPath[] =
    FILE_PATH_LITERAL("localStorage");

// TODO(jorlow): Remove after Chrome 4 ships.
static void MigrateLocalStorageDirectory(const FilePath& data_path) {
  FilePath new_path = data_path.Append(
      DOMStorageContext::kLocalStorageDirectory);
  FilePath old_path = data_path.Append(kLocalStorageOldPath);
  if (!file_util::DirectoryExists(new_path) &&
      file_util::DirectoryExists(old_path)) {
    file_util::Move(old_path, new_path);
  }
}

DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context)
    : last_storage_area_id_(0),
      last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId),
      last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId),
      webkit_context_(webkit_context) {
}

DOMStorageContext::~DOMStorageContext() {
  // This should not go away until all DOM Storage Dispatcher hosts have gone
  // away.  And they remove themselves from this list.
  DCHECK(dispatcher_host_set_.empty());

  for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin());
       iter != storage_namespace_map_.end(); ++iter) {
    delete iter->second;
  }
}

int64 DOMStorageContext::AllocateStorageAreaId() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  return ++last_storage_area_id_;
}

int64 DOMStorageContext::AllocateSessionStorageNamespaceId() {
  if (BrowserThread::CurrentlyOn(BrowserThread::UI))
    return ++last_session_storage_namespace_id_on_ui_thread_;
  return --last_session_storage_namespace_id_on_io_thread_;
}

int64 DOMStorageContext::CloneSessionStorage(int64 original_id) {
  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 clone_id = AllocateSessionStorageNamespaceId();
  BrowserThread::PostTask(
      BrowserThread::WEBKIT, FROM_HERE, NewRunnableFunction(
          &DOMStorageContext::CompleteCloningSessionStorage,
          this, original_id, clone_id));
  return clone_id;
}

void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(!GetStorageArea(id));
  storage_area_map_[id] = storage_area;
}

void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_area->id();
  DCHECK(GetStorageArea(id));
  storage_area_map_.erase(id);
}

DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageAreaMap::iterator iter = storage_area_map_.find(id);
  if (iter == storage_area_map_.end())
    return NULL;
  return iter->second;
}

void DOMStorageContext::DeleteSessionStorageNamespace(int64 namespace_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageNamespaceMap::iterator iter =
      storage_namespace_map_.find(namespace_id);
  if (iter == storage_namespace_map_.end())
    return;
  DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION);
  delete iter->second;
  storage_namespace_map_.erase(iter);
}

DOMStorageNamespace* DOMStorageContext::GetStorageNamespace(
    int64 id, bool allocation_allowed) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
  if (iter != storage_namespace_map_.end())
    return iter->second;
  if (!allocation_allowed)
    return NULL;
  if (id == kLocalStorageNamespaceId)
    return CreateLocalStorage();
  return CreateSessionStorage(id);
}

void DOMStorageContext::RegisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) ==
         dispatcher_host_set_.end());
  dispatcher_host_set_.insert(dispatcher_host);
}

void DOMStorageContext::UnregisterDispatcherHost(
    DOMStorageDispatcherHost* dispatcher_host) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(dispatcher_host_set_.find(dispatcher_host) !=
         dispatcher_host_set_.end());
  dispatcher_host_set_.erase(dispatcher_host);
}

const DOMStorageContext::DispatcherHostSet*
DOMStorageContext::GetDispatcherHostSet() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  return &dispatcher_host_set_;
}

void DOMStorageContext::PurgeMemory() {
  // It is only safe to purge the memory from the LocalStorage namespace,
  // because it is backed by disk and can be reloaded later.  If we purge a
  // SessionStorage namespace, its data will be gone forever, because it isn't
  // currently backed by disk.
  DOMStorageNamespace* local_storage =
      GetStorageNamespace(kLocalStorageNamespaceId, false);
  if (local_storage)
    local_storage->PurgeMemory();
}

void DOMStorageContext::DeleteDataModifiedSince(
    const base::Time& cutoff,
    const char* url_scheme_to_be_skipped,
    const std::vector<string16>& protected_origins) {
  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  PurgeMemory();

  file_util::FileEnumerator file_enumerator(
      webkit_context_->data_path().Append(kLocalStorageDirectory), false,
      file_util::FileEnumerator::FILES);
  for (FilePath path = file_enumerator.Next(); !path.value().empty();
       path = file_enumerator.Next()) {
    WebSecurityOrigin web_security_origin =
        WebSecurityOrigin::createFromDatabaseIdentifier(
            webkit_glue::FilePathToWebString(path.BaseName()));
    if (EqualsASCII(web_security_origin.protocol(), url_scheme_to_be_skipped))
      continue;

    std::vector<string16>::const_iterator find_iter =
        std::find(protected_origins.begin(), protected_origins.end(),
            web_security_origin.databaseIdentifier());
    if (find_iter != protected_origins.end())
      continue;

    file_util::FileEnumerator::FindInfo find_info;
    file_enumerator.GetFindInfo(&find_info);
    if (file_util::HasFileBeenModifiedSince(find_info, cutoff))
      file_util::Delete(path, false);
  }
}

void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));

  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  // TODO(bulach): both this method and DeleteDataModifiedSince could purge
  // only the memory used by the specific file instead of all memory at once.
  // See http://crbug.com/32000
  PurgeMemory();
  file_util::Delete(file_path, false);
}

void DOMStorageContext::DeleteLocalStorageForOrigin(const string16& origin_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  DeleteLocalStorageFile(GetLocalStorageFilePath(origin_id));
}

void DOMStorageContext::DeleteAllLocalStorageFiles() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));

  // Make sure that we don't delete a database that's currently being accessed
  // by unloading all of the databases temporarily.
  PurgeMemory();

  file_util::FileEnumerator file_enumerator(
      webkit_context_->data_path().Append(kLocalStorageDirectory), false,
      file_util::FileEnumerator::FILES);
  for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    if (file_path.Extension() == kLocalStorageExtension)
      file_util::Delete(file_path, false);
  }
}

DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
  FilePath data_path = webkit_context_->data_path();
  FilePath dir_path;
  if (!data_path.empty()) {
    MigrateLocalStorageDirectory(data_path);
    dir_path = data_path.Append(kLocalStorageDirectory);
  }
  DOMStorageNamespace* new_namespace =
      DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
  RegisterStorageNamespace(new_namespace);
  return new_namespace;
}

DOMStorageNamespace* DOMStorageContext::CreateSessionStorage(
    int64 namespace_id) {
  DOMStorageNamespace* new_namespace =
      DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id);
  RegisterStorageNamespace(new_namespace);
  return new_namespace;
}

void DOMStorageContext::RegisterStorageNamespace(
    DOMStorageNamespace* storage_namespace) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  int64 id = storage_namespace->id();
  DCHECK(!GetStorageNamespace(id, false));
  storage_namespace_map_[id] = storage_namespace;
}

/* static */
void DOMStorageContext::CompleteCloningSessionStorage(
    DOMStorageContext* context, int64 existing_id, int64 clone_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
  DOMStorageNamespace* existing_namespace =
      context->GetStorageNamespace(existing_id, false);
  // If nothing exists, then there's nothing to clone.
  if (existing_namespace)
    context->RegisterStorageNamespace(existing_namespace->Copy(clone_id));
}

// static
void DOMStorageContext::ClearLocalState(const FilePath& profile_path,
                                        const char* url_scheme_to_be_skipped) {
  file_util::FileEnumerator file_enumerator(profile_path.Append(
      kLocalStorageDirectory), false, file_util::FileEnumerator::FILES);
  for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    if (file_path.Extension() == kLocalStorageExtension) {
      WebSecurityOrigin web_security_origin =
          WebSecurityOrigin::createFromDatabaseIdentifier(
              webkit_glue::FilePathToWebString(file_path.BaseName()));
      if (!EqualsASCII(web_security_origin.protocol(),
                       url_scheme_to_be_skipped)) {
        file_util::Delete(file_path, false);
      }
    }
  }
}

FilePath DOMStorageContext::GetLocalStorageFilePath(
    const string16& origin_id) const {
  FilePath storageDir = webkit_context_->data_path().Append(
      DOMStorageContext::kLocalStorageDirectory);
  FilePath::StringType id =
      webkit_glue::WebStringToFilePathString(origin_id);
  return storageDir.Append(id.append(kLocalStorageExtension));
}
<|endoftext|>


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

#include "chrome/browser/ui/toolbar/wrench_menu_model.h"

#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/menu_model_test.h"
#include "chrome/test/base/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

class WrenchMenuModelTest : public BrowserWithTestWindowTest,
                            public ui::AcceleratorProvider {
 public:
  // Don't handle accelerators.
  virtual bool GetAcceleratorForCommandId(
      int command_id,
      ui::Accelerator* accelerator) { return false; }
};

// Copies parts of MenuModelTest::Delegate and combines them with the
// WrenchMenuModel since WrenchMenuModel is now a SimpleMenuModel::Delegate and
// not derived from SimpleMenuModel.
class TestWrenchMenuModel : public WrenchMenuModel {
 public:
  TestWrenchMenuModel(ui::AcceleratorProvider* provider,
                      Browser* browser)
      : WrenchMenuModel(provider, browser),
        execute_count_(0),
        checked_count_(0),
        enable_count_(0) {
  }

  // Testing overrides to ui::SimpleMenuModel::Delegate:
  virtual bool IsCommandIdChecked(int command_id) const {
    bool val = WrenchMenuModel::IsCommandIdChecked(command_id);
    if (val)
      checked_count_++;
    return val;
  }

  virtual bool IsCommandIdEnabled(int command_id) const {
    ++enable_count_;
    return true;
  }

  virtual void ExecuteCommand(int command_id) { ++execute_count_; }

  int execute_count_;
  mutable int checked_count_;
  mutable int enable_count_;
};

TEST_F(WrenchMenuModelTest, Basics) {
  TestWrenchMenuModel model(this, browser());
  int itemCount = model.GetItemCount();

  // Verify it has items. The number varies by platform, so we don't check
  // the exact number.
  EXPECT_GT(itemCount, 10);

  // Execute a couple of the items and make sure it gets back to our delegate.
  // We can't use CountEnabledExecutable() here because the encoding menu's
  // delegate is internal, it doesn't use the one we pass in.
  model.ActivatedAt(0);
  EXPECT_TRUE(model.IsEnabledAt(0));
  // Make sure to use the index that is not separator in all configurations.
  model.ActivatedAt(2);
  EXPECT_TRUE(model.IsEnabledAt(2));
  EXPECT_EQ(model.execute_count_, 2);
  EXPECT_EQ(model.enable_count_, 2);

  model.execute_count_ = 0;
  model.enable_count_ = 0;

  // Choose something from the bookmark submenu and make sure it makes it back
  // to the delegate as well.
  int bookmarksModelIndex = -1;
  for (int i = 0; i < itemCount; ++i) {
    if (model.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
      bookmarksModelIndex = i;
      break;
    }
  }
  EXPECT_GT(bookmarksModelIndex, -1);
  ui::MenuModel* bookmarksModel = model.GetSubmenuModelAt(bookmarksModelIndex);
  EXPECT_TRUE(bookmarksModel);
  EXPECT_GT(bookmarksModel->GetItemCount(), 1);
  bookmarksModel->ActivatedAt(1);
  EXPECT_TRUE(bookmarksModel->IsEnabledAt(1));
  EXPECT_EQ(model.execute_count_, 1);
  EXPECT_EQ(model.enable_count_, 1);
}

class EncodingMenuModelTest : public BrowserWithTestWindowTest,
                              public MenuModelTest {
};

TEST_F(EncodingMenuModelTest, IsCommandIdCheckedWithNoTabs) {
  EncodingMenuModel model(browser());
  ASSERT_EQ(NULL, browser()->GetSelectedTabContents());
  EXPECT_FALSE(model.IsCommandIdChecked(IDC_ENCODING_ISO88591));
}
<commit_msg>Unit test for adding global errors to the wrench menu<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/toolbar/wrench_menu_model.h"

#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/global_error.h"
#include "chrome/browser/ui/global_error_service.h"
#include "chrome/browser/ui/global_error_service_factory.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/menu_model_test.h"
#include "chrome/test/base/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// Error class has a menu item.
class MenuError : public GlobalError {
 public:
  explicit MenuError(int command_id)
      : command_id_(command_id),
        execute_count_(0) {
  }

  int execute_count() { return execute_count_; }

  bool HasBadge() OVERRIDE { return false; }
  virtual int GetBadgeResourceID() OVERRIDE {
    ADD_FAILURE();
    return 0;
  }

  virtual bool HasMenuItem() OVERRIDE { return true; }
  virtual int MenuItemCommandID() OVERRIDE { return command_id_; }
  virtual string16 MenuItemLabel() OVERRIDE { return string16(); }
  virtual void ExecuteMenuItem(Browser* browser) OVERRIDE { execute_count_++; }

  virtual bool HasBubbleView() OVERRIDE { return false; }
  virtual void ShowBubbleView(Browser* browser) OVERRIDE { ADD_FAILURE(); }
  virtual int GetBubbleViewIconResourceID() OVERRIDE {
    ADD_FAILURE();
    return 0;
  }
  virtual string16 GetBubbleViewTitle() OVERRIDE {
    ADD_FAILURE();
    return string16();
  }
  virtual string16 GetBubbleViewMessage() OVERRIDE {
    ADD_FAILURE();
    return string16();
  }
  virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE {
    ADD_FAILURE();
    return string16();
  }
  virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE {
    ADD_FAILURE();
    return string16();
  }
  virtual void BubbleViewDidClose() OVERRIDE { ADD_FAILURE(); }
  virtual void BubbleViewAcceptButtonPressed() OVERRIDE { ADD_FAILURE(); }
  virtual void BubbleViewCancelButtonPressed() OVERRIDE { ADD_FAILURE(); }

 private:
  int command_id_;
  int execute_count_;

  DISALLOW_COPY_AND_ASSIGN(MenuError);
};

} // namespace

class WrenchMenuModelTest : public BrowserWithTestWindowTest,
                            public ui::AcceleratorProvider {
 public:
  // Don't handle accelerators.
  virtual bool GetAcceleratorForCommandId(
      int command_id,
      ui::Accelerator* accelerator) { return false; }
};

// Copies parts of MenuModelTest::Delegate and combines them with the
// WrenchMenuModel since WrenchMenuModel is now a SimpleMenuModel::Delegate and
// not derived from SimpleMenuModel.
class TestWrenchMenuModel : public WrenchMenuModel {
 public:
  TestWrenchMenuModel(ui::AcceleratorProvider* provider,
                      Browser* browser)
      : WrenchMenuModel(provider, browser),
        execute_count_(0),
        checked_count_(0),
        enable_count_(0) {
  }

  // Testing overrides to ui::SimpleMenuModel::Delegate:
  virtual bool IsCommandIdChecked(int command_id) const {
    bool val = WrenchMenuModel::IsCommandIdChecked(command_id);
    if (val)
      checked_count_++;
    return val;
  }

  virtual bool IsCommandIdEnabled(int command_id) const {
    ++enable_count_;
    return true;
  }

  virtual void ExecuteCommand(int command_id) { ++execute_count_; }

  int execute_count_;
  mutable int checked_count_;
  mutable int enable_count_;
};

TEST_F(WrenchMenuModelTest, Basics) {
  TestWrenchMenuModel model(this, browser());
  int itemCount = model.GetItemCount();

  // Verify it has items. The number varies by platform, so we don't check
  // the exact number.
  EXPECT_GT(itemCount, 10);

  // Execute a couple of the items and make sure it gets back to our delegate.
  // We can't use CountEnabledExecutable() here because the encoding menu's
  // delegate is internal, it doesn't use the one we pass in.
  model.ActivatedAt(0);
  EXPECT_TRUE(model.IsEnabledAt(0));
  // Make sure to use the index that is not separator in all configurations.
  model.ActivatedAt(2);
  EXPECT_TRUE(model.IsEnabledAt(2));
  EXPECT_EQ(model.execute_count_, 2);
  EXPECT_EQ(model.enable_count_, 2);

  model.execute_count_ = 0;
  model.enable_count_ = 0;

  // Choose something from the bookmark submenu and make sure it makes it back
  // to the delegate as well.
  int bookmarksModelIndex = -1;
  for (int i = 0; i < itemCount; ++i) {
    if (model.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
      bookmarksModelIndex = i;
      break;
    }
  }
  EXPECT_GT(bookmarksModelIndex, -1);
  ui::MenuModel* bookmarksModel = model.GetSubmenuModelAt(bookmarksModelIndex);
  EXPECT_TRUE(bookmarksModel);
  EXPECT_GT(bookmarksModel->GetItemCount(), 1);
  bookmarksModel->ActivatedAt(1);
  EXPECT_TRUE(bookmarksModel->IsEnabledAt(1));
  EXPECT_EQ(model.execute_count_, 1);
  EXPECT_EQ(model.enable_count_, 1);
}

// Tests global error menu items in the wrench menu.
TEST_F(WrenchMenuModelTest, GlobalError) {
  GlobalErrorService* service =
      GlobalErrorServiceFactory::GetForProfile(browser()->profile());
  const int command1 = 1234567;
  // AddGlobalError takes ownership of error1.
  MenuError* error1 = new MenuError(command1);
  service->AddGlobalError(error1);
  const int command2 = 1234568;
  // AddGlobalError takes ownership of error2.
  MenuError* error2 = new MenuError(command2);
  service->AddGlobalError(error2);

  WrenchMenuModel model(this, browser());
  int index1 = model.GetIndexOfCommandId(command1);
  EXPECT_GT(index1, -1);
  int index2 = model.GetIndexOfCommandId(command2);
  EXPECT_GT(index2, -1);

  EXPECT_TRUE(model.IsEnabledAt(index1));
  EXPECT_EQ(0, error1->execute_count());
  model.ActivatedAt(index1);
  EXPECT_EQ(1, error1->execute_count());

  EXPECT_TRUE(model.IsEnabledAt(index2));
  EXPECT_EQ(0, error2->execute_count());
  model.ActivatedAt(index2);
  EXPECT_EQ(1, error1->execute_count());
}

class EncodingMenuModelTest : public BrowserWithTestWindowTest,
                              public MenuModelTest {
};

TEST_F(EncodingMenuModelTest, IsCommandIdCheckedWithNoTabs) {
  EncodingMenuModel model(browser());
  ASSERT_EQ(NULL, browser()->GetSelectedTabContents());
  EXPECT_FALSE(model.IsCommandIdChecked(IDC_ENCODING_ISO88591));
}
<|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_frame/ready_mode/internal/ready_prompt_window.h"

#include <atlctrls.h>
#include <Shellapi.h>  // Must appear before atlctrlx.h

// These seem to be required by atlctrlx?
template<class A>
A min(A const& a, A const& b) { return a < b ? a : b; }

template<class A>
A max(A const& a, A const& b) { return a > b ? a : b; }

#include <atlctrlx.h>

#include "base/compiler_specific.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
#include "chrome_frame/ready_mode/internal/url_launcher.h"
#include "chrome_frame/simple_resource_loader.h"
#include "grit/chromium_strings.h"

ReadyPromptWindow::ReadyPromptWindow(
    InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
    UrlLauncher* url_launcher)
    : frame_(frame),
      ready_mode_state_(ready_mode_state),
      url_launcher_(url_launcher),
      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
ReadyPromptWindow::~ReadyPromptWindow() {
}

base::WeakPtr<ReadyPromptWindow> ReadyPromptWindow::CreateInstance(
    InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
    UrlLauncher* url_launcher) {
  DCHECK(frame != NULL);
  DCHECK(ready_mode_state != NULL);
  DCHECK(url_launcher != NULL);

  base::WeakPtr<ReadyPromptWindow> instance((new ReadyPromptWindow(
      frame, ready_mode_state, url_launcher))->weak_ptr_factory_.GetWeakPtr());

  DCHECK(!instance->IsWindow());

  if (instance->Create(frame->GetFrameWindow()) == NULL) {
    DPLOG(ERROR) << "Failed to create HWND for ReadyPromptWindow.";
    return base::WeakPtr<ReadyPromptWindow>();
  }

  // Subclass the "Learn more." text to make it behave like a link. Clicks are
  // routed to OnLearnMore().
  CWindow rte = instance->GetDlgItem(IDC_PROMPT_LINK);
  instance->link_.reset(new CHyperLink());
  instance->link_->SubclassWindow(rte);
  instance->link_->SetHyperLinkExtendedStyle(HLINK_NOTIFYBUTTON,
                                             HLINK_NOTIFYBUTTON);

  return instance;
}

void ReadyPromptWindow::OnDestroy() {
  frame_ = NULL;
}

BOOL ReadyPromptWindow::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) {
  DlgResize_Init(false);  // false => 'no gripper'
  return TRUE;
}

LRESULT ReadyPromptWindow::OnYes(WORD /*wNotifyCode*/,
                                 WORD /*wID*/,
                                 HWND /*hWndCtl*/,
                                 BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->AcceptChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnRemindMeLater(WORD /*wNotifyCode*/,
                                           WORD /*wID*/,
                                           HWND /*hWndCtl*/,
                                           BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->TemporarilyDeclineChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnNo(WORD /*wNotifyCode*/,
                                WORD /*wID*/,
                                HWND /*hWndCtl*/,
                                BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->PermanentlyDeclineChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnLearnMore(WORD /*wParam*/,
                                       LPNMHDR /*lParam*/,
                                       BOOL& /*bHandled*/) {
  url_launcher_->LaunchUrl(SimpleResourceLoader::Get(
      IDS_CHROME_FRAME_READY_MODE_LEARN_MORE_URL));
  return 0;
}

void ReadyPromptWindow::OnFinalMessage(HWND) {
  delete this;
}
<commit_msg>Replace one unfortunate hack with a somewhat better one. The included atlctrlx.h relies on min and max macros, which are generally bad and especially so in combination with STL.<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_frame/ready_mode/internal/ready_prompt_window.h"

#include <atlctrls.h>
#include <Shellapi.h>

#include "base/compiler_specific.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
#include "chrome_frame/ready_mode/internal/url_launcher.h"
#include "chrome_frame/simple_resource_loader.h"
#include "grit/chromium_strings.h"

// atlctrlx.h requires 'min' and 'max' macros, the definition of which conflicts
// with STL headers. Hence we include them out of the order defined by style
// guidelines. As a result you may not refer to std::min or std::max in this
// file.
#include <minmax.h>  // NOLINT
#include <atlctrlx.h>  // NOLINT

ReadyPromptWindow::ReadyPromptWindow(
    InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
    UrlLauncher* url_launcher)
    : frame_(frame),
      ready_mode_state_(ready_mode_state),
      url_launcher_(url_launcher),
      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
ReadyPromptWindow::~ReadyPromptWindow() {
}

base::WeakPtr<ReadyPromptWindow> ReadyPromptWindow::CreateInstance(
    InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
    UrlLauncher* url_launcher) {
  DCHECK(frame != NULL);
  DCHECK(ready_mode_state != NULL);
  DCHECK(url_launcher != NULL);

  base::WeakPtr<ReadyPromptWindow> instance((new ReadyPromptWindow(
      frame, ready_mode_state, url_launcher))->weak_ptr_factory_.GetWeakPtr());

  DCHECK(!instance->IsWindow());

  if (instance->Create(frame->GetFrameWindow()) == NULL) {
    DPLOG(ERROR) << "Failed to create HWND for ReadyPromptWindow.";
    return base::WeakPtr<ReadyPromptWindow>();
  }

  // Subclass the "Learn more." text to make it behave like a link. Clicks are
  // routed to OnLearnMore().
  CWindow rte = instance->GetDlgItem(IDC_PROMPT_LINK);
  instance->link_.reset(new CHyperLink());
  instance->link_->SubclassWindow(rte);
  instance->link_->SetHyperLinkExtendedStyle(HLINK_NOTIFYBUTTON,
                                             HLINK_NOTIFYBUTTON);

  return instance;
}

void ReadyPromptWindow::OnDestroy() {
  frame_ = NULL;
}

BOOL ReadyPromptWindow::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) {
  DlgResize_Init(false);  // false => 'no gripper'
  return TRUE;
}

LRESULT ReadyPromptWindow::OnYes(WORD /*wNotifyCode*/,
                                 WORD /*wID*/,
                                 HWND /*hWndCtl*/,
                                 BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->AcceptChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnRemindMeLater(WORD /*wNotifyCode*/,
                                           WORD /*wID*/,
                                           HWND /*hWndCtl*/,
                                           BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->TemporarilyDeclineChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnNo(WORD /*wNotifyCode*/,
                                WORD /*wID*/,
                                HWND /*hWndCtl*/,
                                BOOL& /*bHandled*/) {
  frame_->CloseInfobar();
  ready_mode_state_->PermanentlyDeclineChromeFrame();
  return 0;
}

LRESULT ReadyPromptWindow::OnLearnMore(WORD /*wParam*/,
                                       LPNMHDR /*lParam*/,
                                       BOOL& /*bHandled*/) {
  url_launcher_->LaunchUrl(SimpleResourceLoader::Get(
      IDS_CHROME_FRAME_READY_MODE_LEARN_MORE_URL));
  return 0;
}

void ReadyPromptWindow::OnFinalMessage(HWND) {
  delete this;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Pavlo Lavrenenko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <Rubik.h>
#include <ObjectManager.h>
#include <RenderManager.h>
#include <Window.h>
#include <OpenGL.h>
#include <Shader.h>
#include <Entity.h>
#include <Font.h>
#include <Layout.h>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>

namespace Rubik {

Rubik::Rubik() {
    std::srand(static_cast<int>(std::time(nullptr)));
}

int Rubik::getShuffles() const {
    return this->shuffles;
}

void Rubik::setShuffles(int shuffles) {
    this->shuffles = shuffles;
}

void Rubik::onMouseMotion(int x, int y) {
    static Graphene::MousePosition mousePosition(this->getWindow()->getMousePosition());
    const Graphene::MouseState& mouseState = this->getWindow()->getMouseState();

    Math::Vec3 motionDirection(static_cast<float>(x - mousePosition.first), static_cast<float>(y - mousePosition.second), 0.0f);
    mousePosition = this->getWindow()->getMousePosition();

    int objectId = -1;
    bool isCubeSelected = false;
    bool isFrontCubeSelected = false;

    switch (this->state) {
        case GameState::RUNNING:
            if (mouseState[Graphene::MouseButton::BUTTON_LEFT] || mouseState[Graphene::MouseButton::BUTTON_RIGHT]) {
                int pickupX = x * this->pickupBuffer->getWidth() / this->getWindow()->getWidth();
                int pickupY = (this->getWindow()->getHeight() - y) * this->pickupBuffer->getHeight() / this->getWindow()->getHeight();
                this->pickupBuffer->getPixel(pickupX, pickupY, GL_RED_INTEGER, GL_INT, &objectId);

                isCubeSelected = (std::find(this->puzzleObjects.begin(), this->puzzleObjects.end(), objectId) != this->puzzleObjects.end());
                isFrontCubeSelected = (isCubeSelected && std::get<2>(this->puzzle->getCubePosition(objectId)) == 0);
            }

            if (mouseState[Graphene::MouseButton::BUTTON_LEFT] && !mouseState[Graphene::MouseButton::BUTTON_RIGHT]) {
                if (isFrontCubeSelected) {
                    this->rotateCube(objectId, motionDirection);
                }
            } else if (mouseState[Graphene::MouseButton::BUTTON_RIGHT] && !mouseState[Graphene::MouseButton::BUTTON_LEFT]) {
                if (isCubeSelected) {
                    this->rotateCube(-1, motionDirection);
                }
            }
            break;

        default:
            break;
    }
}

void Rubik::onKeyboardKey(Graphene::KeyboardKey key, bool state) {
    static bool pausePressed = false;
    static float rotationSpeed = 0.0f;

    switch (this->state) {
        case GameState::RUNNING:
            if (key == Graphene::KeyboardKey::KEY_S) {
                if (state) {
                    if (rotationSpeed == 0.0f) {
                        rotationSpeed = this->puzzle->getRotationSpeed();
                        this->puzzle->setRotationSpeed(rotationSpeed * 2.0f);
                    }
                } else {
                    this->puzzle->setRotationSpeed(rotationSpeed);
                    rotationSpeed = 0.0f;
                }
            }
            // Fall through

        case GameState::PAUSED:
            if (key == Graphene::KeyboardKey::KEY_P) {
                if (state) {
                    if (!pausePressed) {
                        this->state = (this->state == GameState::RUNNING) ? GameState::PAUSED : GameState::RUNNING;
                        pausePressed = true;
                    }
                } else {
                    pausePressed = false;
                }
            }
            break;

        default:
            break;
    }
}

void Rubik::onSetup() {
    auto& renderManager = Graphene::GetRenderManager();
    auto& objectManager = Graphene::GetObjectManager();

    renderManager.setRenderShader(Graphene::RenderStep::BUFFER, objectManager.createShader("shaders/object_pickup.shader"));
    renderManager.setRenderCallback(Graphene::RenderStep::BUFFER, [](const std::shared_ptr<Graphene::Object> object) {
        auto& renderManager = Graphene::GetRenderManager();

        auto renderShader = renderManager.getRenderShader(renderManager.getRenderStep());
        renderShader->setUniform("objectId", object->getId());
    });

    this->setupScene();
    this->setupUI();
}

void Rubik::onIdle() {
    this->updateScene();
    this->updateUI();

    const Graphene::KeyboardState& keyboardState = this->getWindow()->getKeyboardState();
    if (this->state == GameState::RUNNING && !keyboardState[Graphene::KeyboardKey::KEY_S]) {
        this->gameTime += this->getFrameTime();
    }
}

void Rubik::setupScene() {
    /* Setup scene */

    auto scene = this->createScene();
    scene->setAmbientEnergy(0.2f);

    auto player = scene->createNode();
    auto cube = scene->createNode();
    this->puzzle = std::make_shared<Puzzle>();

    auto sceneRoot = scene->getRootNode();
    sceneRoot->attachNode(player);
    sceneRoot->attachNode(cube);

    /* Populate scene with objects */

    auto& objectManager = Graphene::GetObjectManager();
    auto& renderManager = Graphene::GetRenderManager();
    renderManager.setLightPass(true);

    auto background = objectManager.createEntity("assets/background.entity");
    background->translate(0.0f, 0.0f, 5.0f);
    background->scale(25.0f, 25.0f, 1.0f);
    sceneRoot->attachObject(background);

    auto camera = objectManager.createCamera(Graphene::ProjectionType::PERSPECTIVE);
    auto light = objectManager.createLight(Graphene::LightType::DIRECTED);

    player->attachObject(camera);
    player->attachObject(light);
    player->translate(0.25f, -0.25f, -4.5f);

    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            for (int k = -1; k <= 1; k++) {
                auto cubepart = scene->createNode();
                cube->attachNode(cubepart);

                auto entity = objectManager.createEntity("assets/cubepart.entity");
                entity->translate(static_cast<float>(i), static_cast<float>(j), static_cast<float>(k));
                cubepart->attachObject(entity);

                this->puzzle->attachCube(entity);
                this->puzzleObjects.push_back(entity->getId());
            }
        }
    }

    cube->roll(-30.0f);
    cube->yaw(-30.0f);
    this->puzzle->shuffle(this->shuffles);

    /* Update default viewport with camera */

    auto window = this->getWindow();
    auto viewport = window->createViewport(0, 0, window->getWidth(), window->getHeight());
    viewport->setCamera(camera);

    /* Create framebuffer for object ID rendering and picking */

    this->pickupBuffer = this->createFrameBuffer(window->getWidth() / 2, window->getHeight() / 2, GL_R32I);
    auto pickupViewport = pickupBuffer->createViewport(0, 0, this->pickupBuffer->getWidth(), this->pickupBuffer->getHeight());
    pickupViewport->setCamera(camera);
}

void Rubik::setupUI() {
    /* Setup scene */

    auto uiScene = this->createScene();
    auto uiRootNode = uiScene->getRootNode();

    /* Populate scene with objects */

    auto& objectManager = Graphene::GetObjectManager();
    auto camera = objectManager.createCamera(Graphene::ProjectionType::ORTHOGRAPHIC);
    camera->setNearPlane(-1.0f);
    camera->setFarPlane(1.0f);

    auto font = std::make_shared<Graphene::Font>("fonts/dejavu-sans.ttf", 14);
    this->timeLabel = std::make_shared<Graphene::Label>(200, 20, font);
    this->movesLabel = std::make_shared<Graphene::Label>(200, 20, font);
    this->promptLabel = std::make_shared<Graphene::Label>(200, 20, font);

    uiRootNode->attachObject(camera);
    uiRootNode->attachObject(this->timeLabel);
    uiRootNode->attachObject(this->movesLabel);
    uiRootNode->attachObject(this->promptLabel);

    /* Arrange UI elements */

    auto window = this->getWindow();

    auto uiLayout = std::make_shared<Graphene::Layout>();
    uiLayout->addComponent(this->timeLabel, 10, window->getHeight() - 20);
    uiLayout->addComponent(this->movesLabel, 10, window->getHeight() - 40);
    uiLayout->addComponent(this->promptLabel, 10, 10);

    /* Update viewport with camera */

    auto overlay = window->createOverlay(0, 0, window->getWidth(), window->getHeight());
    overlay->setCamera(camera);
    overlay->setLayout(uiLayout);
}

void Rubik::updateScene() {
    const Graphene::KeyboardState& keyboardState = this->getWindow()->getKeyboardState();

    switch (this->state) {
        case GameState::RUNNING:
            if (this->puzzle->isSolved()) {
                this->state = GameState::FINISHED;
            } else if (keyboardState[Graphene::KeyboardKey::KEY_ESCAPE]) {
                this->state = GameState::QUIT;
            } else if (keyboardState[Graphene::KeyboardKey::KEY_S]) {
                this->puzzle->selectCube(this->puzzleObjects[std::rand() % this->puzzleObjects.size()]);
                this->puzzle->setAnimationState(static_cast<AnimationState>(std::rand() % 4 + 1));
            }

            this->puzzle->update(this->getFrameTime());
            break;

        case GameState::QUIT:
            if (keyboardState[Graphene::KeyboardKey::KEY_Y]) {
                this->exit(0);
            } else if (keyboardState[Graphene::KeyboardKey::KEY_N]) {
                this->state = GameState::RUNNING;
            }
            break;

        case GameState::FINISHED:
            if (keyboardState[Graphene::KeyboardKey::KEY_N]) {
                this->exit(0);
            } else if (keyboardState[Graphene::KeyboardKey::KEY_Y]) {
                this->moves = 0;
                this->gameTime = 0.0f;
                this->state = GameState::RUNNING;
                this->puzzle->shuffle(this->shuffles);
            }
            break;

        default:
            break;
    }
}

void Rubik::updateUI() {
    int gameTime = static_cast<int>(this->gameTime);
    int seconds = gameTime % 60;
    int minutes = gameTime / 60;
    int hours = gameTime / 3600;

    std::wstringstream time;
    time << "Time: " << std::setw(2) << std::setfill(L'0') << hours << ":"
                     << std::setw(2) << std::setfill(L'0') << minutes << ":"
                     << std::setw(2) << std::setfill(L'0') << seconds;
    this->timeLabel->setText(time.str());

    std::wstringstream moves;
    moves << "Moves: " << this->moves;
    this->movesLabel->setText(moves.str());

    switch (this->state) {
        case GameState::FINISHED:
            this->promptLabel->setText(L"Done! New game? Y/N");
            this->promptLabel->setVisible(true);
            break;

        case GameState::PAUSED:
            this->promptLabel->setText(L"Paused");
            this->promptLabel->setVisible(true);
            break;

        case GameState::QUIT:
            this->promptLabel->setText(L"Quit? Y/N");
            this->promptLabel->setVisible(true);
            break;

        default:
            this->promptLabel->setVisible(false);
            break;
    }
}

void Rubik::rotateCube(int objectId, const Math::Vec3& direction) {
    if (this->state == GameState::PAUSED) {
        return;  // No action on pause
    }

    if (direction.length() < 1.5f) {
        return;  // Movement is too short
    }

    if (objectId != -1 && this->puzzle->getAnimationState() == AnimationState::IDLE) {
        this->moves++;
    }

    float xDirection = direction.get(Math::Vec3::X);
    float yDirection = direction.get(Math::Vec3::Y);
    AnimationState puzzleState = AnimationState::IDLE;

    if (fabsf(xDirection) > fabsf(yDirection)) {
        puzzleState = (xDirection > 0) ? AnimationState::RIGHT_ROTATION : AnimationState::LEFT_ROTATION;
    } else {
        puzzleState = (yDirection > 0) ? AnimationState::DOWN_ROTATION : AnimationState::UP_ROTATION;
    }

    this->puzzle->selectCube(objectId);
    this->puzzle->setAnimationState(puzzleState);
}

}  // namespace Rubik
<commit_msg>Change BUFFER render state setup to fit upstream changes<commit_after>/*
 * Copyright (c) 2013 Pavlo Lavrenenko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <Rubik.h>
#include <ObjectManager.h>
#include <RenderManager.h>
#include <RenderState.h>
#include <Window.h>
#include <OpenGL.h>
#include <Shader.h>
#include <Entity.h>
#include <Font.h>
#include <Layout.h>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>

namespace Rubik {

Rubik::Rubik() {
    std::srand(static_cast<int>(std::time(nullptr)));
}

int Rubik::getShuffles() const {
    return this->shuffles;
}

void Rubik::setShuffles(int shuffles) {
    this->shuffles = shuffles;
}

void Rubik::onMouseMotion(int x, int y) {
    static Graphene::MousePosition mousePosition(this->getWindow()->getMousePosition());
    const Graphene::MouseState& mouseState = this->getWindow()->getMouseState();

    Math::Vec3 motionDirection(static_cast<float>(x - mousePosition.first), static_cast<float>(y - mousePosition.second), 0.0f);
    mousePosition = this->getWindow()->getMousePosition();

    int objectId = -1;
    bool isCubeSelected = false;
    bool isFrontCubeSelected = false;

    switch (this->state) {
        case GameState::RUNNING:
            if (mouseState[Graphene::MouseButton::BUTTON_LEFT] || mouseState[Graphene::MouseButton::BUTTON_RIGHT]) {
                int pickupX = x * this->pickupBuffer->getWidth() / this->getWindow()->getWidth();
                int pickupY = (this->getWindow()->getHeight() - y) * this->pickupBuffer->getHeight() / this->getWindow()->getHeight();
                this->pickupBuffer->getPixel(pickupX, pickupY, GL_RED_INTEGER, GL_INT, &objectId);

                isCubeSelected = (std::find(this->puzzleObjects.begin(), this->puzzleObjects.end(), objectId) != this->puzzleObjects.end());
                isFrontCubeSelected = (isCubeSelected && std::get<2>(this->puzzle->getCubePosition(objectId)) == 0);
            }

            if (mouseState[Graphene::MouseButton::BUTTON_LEFT] && !mouseState[Graphene::MouseButton::BUTTON_RIGHT]) {
                if (isFrontCubeSelected) {
                    this->rotateCube(objectId, motionDirection);
                }
            } else if (mouseState[Graphene::MouseButton::BUTTON_RIGHT] && !mouseState[Graphene::MouseButton::BUTTON_LEFT]) {
                if (isCubeSelected) {
                    this->rotateCube(-1, motionDirection);
                }
            }
            break;

        default:
            break;
    }
}

void Rubik::onKeyboardKey(Graphene::KeyboardKey key, bool state) {
    static bool pausePressed = false;
    static float rotationSpeed = 0.0f;

    switch (this->state) {
        case GameState::RUNNING:
            if (key == Graphene::KeyboardKey::KEY_S) {
                if (state) {
                    if (rotationSpeed == 0.0f) {
                        rotationSpeed = this->puzzle->getRotationSpeed();
                        this->puzzle->setRotationSpeed(rotationSpeed * 2.0f);
                    }
                } else {
                    this->puzzle->setRotationSpeed(rotationSpeed);
                    rotationSpeed = 0.0f;
                }
            }
            // Fall through

        case GameState::PAUSED:
            if (key == Graphene::KeyboardKey::KEY_P) {
                if (state) {
                    if (!pausePressed) {
                        this->state = (this->state == GameState::RUNNING) ? GameState::PAUSED : GameState::RUNNING;
                        pausePressed = true;
                    }
                } else {
                    pausePressed = false;
                }
            }
            break;

        default:
            break;
    }
}

void Rubik::onSetup() {
    Graphene::RenderCallback renderCallback([](Graphene::RenderState* renderState, const std::shared_ptr<Graphene::Object> object) {
        renderState->getShader()->setUniform("objectId", object->getId());
    });

    auto renderState = Graphene::GetRenderManager().getRenderState(Graphene::RenderStateType::BUFFER);
    renderState->setShader(Graphene::GetObjectManager().createShader("shaders/object_pickup.shader"));
    renderState->setCallback(renderCallback);

    this->setupScene();
    this->setupUI();
}

void Rubik::onIdle() {
    this->updateScene();
    this->updateUI();

    const Graphene::KeyboardState& keyboardState = this->getWindow()->getKeyboardState();
    if (this->state == GameState::RUNNING && !keyboardState[Graphene::KeyboardKey::KEY_S]) {
        this->gameTime += this->getFrameTime();
    }
}

void Rubik::setupScene() {
    /* Setup scene */

    auto scene = this->createScene();
    scene->setAmbientEnergy(0.2f);

    auto player = scene->createNode();
    auto cube = scene->createNode();
    this->puzzle = std::make_shared<Puzzle>();

    auto sceneRoot = scene->getRootNode();
    sceneRoot->attachNode(player);
    sceneRoot->attachNode(cube);

    /* Populate scene with objects */

    auto& objectManager = Graphene::GetObjectManager();
    auto& renderManager = Graphene::GetRenderManager();
    renderManager.setLightPass(true);

    auto background = objectManager.createEntity("assets/background.entity");
    background->translate(0.0f, 0.0f, 5.0f);
    background->scale(25.0f, 25.0f, 1.0f);
    sceneRoot->attachObject(background);

    auto camera = objectManager.createCamera(Graphene::ProjectionType::PERSPECTIVE);
    auto light = objectManager.createLight(Graphene::LightType::DIRECTED);

    player->attachObject(camera);
    player->attachObject(light);
    player->translate(0.25f, -0.25f, -4.5f);

    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            for (int k = -1; k <= 1; k++) {
                auto cubepart = scene->createNode();
                cube->attachNode(cubepart);

                auto entity = objectManager.createEntity("assets/cubepart.entity");
                entity->translate(static_cast<float>(i), static_cast<float>(j), static_cast<float>(k));
                cubepart->attachObject(entity);

                this->puzzle->attachCube(entity);
                this->puzzleObjects.push_back(entity->getId());
            }
        }
    }

    cube->roll(-30.0f);
    cube->yaw(-30.0f);
    this->puzzle->shuffle(this->shuffles);

    /* Update default viewport with camera */

    auto window = this->getWindow();
    auto viewport = window->createViewport(0, 0, window->getWidth(), window->getHeight());
    viewport->setCamera(camera);

    /* Create framebuffer for object ID rendering and picking */

    this->pickupBuffer = this->createFrameBuffer(window->getWidth() / 2, window->getHeight() / 2, GL_R32I);
    auto pickupViewport = pickupBuffer->createViewport(0, 0, this->pickupBuffer->getWidth(), this->pickupBuffer->getHeight());
    pickupViewport->setCamera(camera);
}

void Rubik::setupUI() {
    /* Setup scene */

    auto uiScene = this->createScene();
    auto uiRootNode = uiScene->getRootNode();

    /* Populate scene with objects */

    auto& objectManager = Graphene::GetObjectManager();
    auto camera = objectManager.createCamera(Graphene::ProjectionType::ORTHOGRAPHIC);
    camera->setNearPlane(-1.0f);
    camera->setFarPlane(1.0f);

    auto font = std::make_shared<Graphene::Font>("fonts/dejavu-sans.ttf", 14);
    this->timeLabel = std::make_shared<Graphene::Label>(200, 20, font);
    this->movesLabel = std::make_shared<Graphene::Label>(200, 20, font);
    this->promptLabel = std::make_shared<Graphene::Label>(200, 20, font);

    uiRootNode->attachObject(camera);
    uiRootNode->attachObject(this->timeLabel);
    uiRootNode->attachObject(this->movesLabel);
    uiRootNode->attachObject(this->promptLabel);

    /* Arrange UI elements */

    auto window = this->getWindow();

    auto uiLayout = std::make_shared<Graphene::Layout>();
    uiLayout->addComponent(this->timeLabel, 10, window->getHeight() - 20);
    uiLayout->addComponent(this->movesLabel, 10, window->getHeight() - 40);
    uiLayout->addComponent(this->promptLabel, 10, 10);

    /* Update viewport with camera */

    auto overlay = window->createOverlay(0, 0, window->getWidth(), window->getHeight());
    overlay->setCamera(camera);
    overlay->setLayout(uiLayout);
}

void Rubik::updateScene() {
    const Graphene::KeyboardState& keyboardState = this->getWindow()->getKeyboardState();

    switch (this->state) {
        case GameState::RUNNING:
            if (this->puzzle->isSolved()) {
                this->state = GameState::FINISHED;
            } else if (keyboardState[Graphene::KeyboardKey::KEY_ESCAPE]) {
                this->state = GameState::QUIT;
            } else if (keyboardState[Graphene::KeyboardKey::KEY_S]) {
                this->puzzle->selectCube(this->puzzleObjects[std::rand() % this->puzzleObjects.size()]);
                this->puzzle->setAnimationState(static_cast<AnimationState>(std::rand() % 4 + 1));
            }

            this->puzzle->update(this->getFrameTime());
            break;

        case GameState::QUIT:
            if (keyboardState[Graphene::KeyboardKey::KEY_Y]) {
                this->exit(0);
            } else if (keyboardState[Graphene::KeyboardKey::KEY_N]) {
                this->state = GameState::RUNNING;
            }
            break;

        case GameState::FINISHED:
            if (keyboardState[Graphene::KeyboardKey::KEY_N]) {
                this->exit(0);
            } else if (keyboardState[Graphene::KeyboardKey::KEY_Y]) {
                this->moves = 0;
                this->gameTime = 0.0f;
                this->state = GameState::RUNNING;
                this->puzzle->shuffle(this->shuffles);
            }
            break;

        default:
            break;
    }
}

void Rubik::updateUI() {
    int gameTime = static_cast<int>(this->gameTime);
    int seconds = gameTime % 60;
    int minutes = gameTime / 60;
    int hours = gameTime / 3600;

    std::wstringstream time;
    time << "Time: " << std::setw(2) << std::setfill(L'0') << hours << ":"
                     << std::setw(2) << std::setfill(L'0') << minutes << ":"
                     << std::setw(2) << std::setfill(L'0') << seconds;
    this->timeLabel->setText(time.str());

    std::wstringstream moves;
    moves << "Moves: " << this->moves;
    this->movesLabel->setText(moves.str());

    switch (this->state) {
        case GameState::FINISHED:
            this->promptLabel->setText(L"Done! New game? Y/N");
            this->promptLabel->setVisible(true);
            break;

        case GameState::PAUSED:
            this->promptLabel->setText(L"Paused");
            this->promptLabel->setVisible(true);
            break;

        case GameState::QUIT:
            this->promptLabel->setText(L"Quit? Y/N");
            this->promptLabel->setVisible(true);
            break;

        default:
            this->promptLabel->setVisible(false);
            break;
    }
}

void Rubik::rotateCube(int objectId, const Math::Vec3& direction) {
    if (this->state == GameState::PAUSED) {
        return;  // No action on pause
    }

    if (direction.length() < 1.5f) {
        return;  // Movement is too short
    }

    if (objectId != -1 && this->puzzle->getAnimationState() == AnimationState::IDLE) {
        this->moves++;
    }

    float xDirection = direction.get(Math::Vec3::X);
    float yDirection = direction.get(Math::Vec3::Y);
    AnimationState puzzleState = AnimationState::IDLE;

    if (fabsf(xDirection) > fabsf(yDirection)) {
        puzzleState = (xDirection > 0) ? AnimationState::RIGHT_ROTATION : AnimationState::LEFT_ROTATION;
    } else {
        puzzleState = (yDirection > 0) ? AnimationState::DOWN_ROTATION : AnimationState::UP_ROTATION;
    }

    this->puzzle->selectCube(objectId);
    this->puzzle->setAnimationState(puzzleState);
}

}  // namespace Rubik
<|endoftext|>