<commit_before>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

/** \class RooCBShape
    \ingroup Roofit

PDF implementing the Crystal Ball line shape.
**/

#include "RooCBShape.h"

#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooMath.h"
#include "BatchHelpers.h"
#include "RooVDTHeaders.h"

#include "TMath.h"

#include <cmath>

using namespace std;

ClassImp(RooCBShape);

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::ApproxErf(Double_t arg) const
{
  static const double erflim = 5.0;
  if( arg > erflim )
    return 1.0;
  if( arg < -erflim )
    return -1.0;

  return RooMath::erf(arg);
}

////////////////////////////////////////////////////////////////////////////////

RooCBShape::RooCBShape(const char *name, const char *title,
             RooAbsReal& _m, RooAbsReal& _m0, RooAbsReal& _sigma,
             RooAbsReal& _alpha, RooAbsReal& _n) :
  RooAbsPdf(name, title),
  m("m", "Dependent", this, _m),
  m0("m0", "M0", this, _m0),
  sigma("sigma", "Sigma", this, _sigma),
  alpha("alpha", "Alpha", this, _alpha),
  n("n", "Order", this, _n)
{
}

////////////////////////////////////////////////////////////////////////////////

RooCBShape::RooCBShape(const RooCBShape& other, const char* name) :
  RooAbsPdf(other, name), m("m", this, other.m), m0("m0", this, other.m0),
  sigma("sigma", this, other.sigma), alpha("alpha", this, other.alpha),
  n("n", this, other.n)
{
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::evaluate() const {
  Double_t t = (m-m0)/sigma;
  if (alpha < 0) t = -t;

  Double_t absAlpha = fabs((Double_t)alpha);

  if (t >= -absAlpha) {
    return exp(-0.5*t*t);
  }
  else {
    Double_t a =  TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    Double_t b= n/absAlpha - absAlpha;

    return a/TMath::Power(b - t, n);
  }
}

////////////////////////////////////////////////////////////////////////////////

namespace {
//Author: Emmanouil Michalainas, CERN 21 August 2019

template<class Tm, class Tm0, class Tsigma, class Talpha, class Tn>
void compute(	size_t batchSize,
	double * __restrict output,
	Tm M, Tm0 M0, Tsigma S, Talpha A, Tn N)
{
  for (size_t i=0; i<batchSize; i++) {
    const double t = (M[i]-M0[i]) / S[i];
    if ((A[i]>0 && t>=-A[i])   ||   (A[i]<0 && -t>=A[i])) {
      output[i] = -0.5*t*t;
    } else {
      output[i] = N[i] / (N[i] -A[i]*A[i] -A[i]*t);
      output[i] = _rf_fast_log(output[i]);
      output[i] *= N[i];
      output[i] -= 0.5*A[i]*A[i];
    }
  }

  for (size_t i=0; i<batchSize; i++) {
    output[i] = _rf_fast_exp(output[i]);
  }
}
};

RooSpan<double> RooCBShape::evaluateBatch(std::size_t begin, std::size_t batchSize) const {
  using namespace BatchHelpers;

  EvaluateInfo info = getInfo( {&m, &m0, &sigma, &alpha, &n}, begin, batchSize );
  if (info.nBatches == 0) {
    return {};
  }
  auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
  auto mData = m.getValBatch(begin, info.size);

  if (info.nBatches==1 && !mData.empty()) {
    compute(info.size, output.data(), mData.data(),
    BracketAdapter<double> (m0),
    BracketAdapter<double> (sigma),
    BracketAdapter<double> (alpha),
    BracketAdapter<double> (n));
  }
  else {
    compute(info.size, output.data(),
    BracketAdapterWithMask (m,m.getValBatch(begin,info.size)),
    BracketAdapterWithMask (m0,m0.getValBatch(begin,info.size)),
    BracketAdapterWithMask (sigma,sigma.getValBatch(begin,info.size)),
    BracketAdapterWithMask (alpha,alpha.getValBatch(begin,info.size)),
    BracketAdapterWithMask (n,n.getValBatch(begin,info.size)));
  }
  return output;
}

////////////////////////////////////////////////////////////////////////////////

Int_t RooCBShape::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
{
  if( matchArgs(allVars,analVars,m) )
    return 1 ;

  return 0;
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::analyticalIntegral(Int_t code, const char* rangeName) const
{
  static const double sqrtPiOver2 = 1.2533141373;
  static const double sqrt2 = 1.4142135624;

  R__ASSERT(code==1);
  double result = 0.0;
  bool useLog = false;

  if( fabs(n-1.0) < 1.0e-05 )
    useLog = true;

  double sig = fabs((Double_t)sigma);

  double tmin = (m.min(rangeName)-m0)/sig;
  double tmax = (m.max(rangeName)-m0)/sig;

  if(alpha < 0) {
    double tmp = tmin;
    tmin = -tmax;
    tmax = -tmp;
  }

  double absAlpha = fabs((Double_t)alpha);

  if( tmin >= -absAlpha ) {
    result += sig*sqrtPiOver2*(   ApproxErf(tmax/sqrt2)
                                - ApproxErf(tmin/sqrt2) );
  }
  else if( tmax <= -absAlpha ) {
    double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    double b = n/absAlpha - absAlpha;

    if(useLog) {
      result += a*sig*( log(b-tmin) - log(b-tmax) );
    }
    else {
      result += a*sig/(1.0-n)*(   1.0/(TMath::Power(b-tmin,n-1.0))
                                - 1.0/(TMath::Power(b-tmax,n-1.0)) );
    }
  }
  else {
    double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    double b = n/absAlpha - absAlpha;

    double term1 = 0.0;
    if(useLog) {
      term1 = a*sig*(  log(b-tmin) - log(n/absAlpha));
    }
    else {
      term1 = a*sig/(1.0-n)*(   1.0/(TMath::Power(b-tmin,n-1.0))
                              - 1.0/(TMath::Power(n/absAlpha,n-1.0)) );
    }

    double term2 = sig*sqrtPiOver2*(   ApproxErf(tmax/sqrt2)
                                     - ApproxErf(-absAlpha/sqrt2) );

    result += term1 + term2;
  }

  return result != 0. ? result : 1.E-300;
}

////////////////////////////////////////////////////////////////////////////////
/// Advertise that we know the maximum of self for given (m0,alpha,n,sigma)

Int_t RooCBShape::getMaxVal(const RooArgSet& vars) const
{
  RooArgSet dummy ;

  if (matchArgs(vars,dummy,m)) {
    return 1 ;
  }
  return 0 ;
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::maxVal(Int_t code) const
{
  R__ASSERT(code==1) ;

  // The maximum value for given (m0,alpha,n,sigma)
  return 1.0 ;
}
<commit_msg>Fix computing maximum value for RooCBShape The maximum value for RooCBSHape is use din generate() to speedup Accept/reject The maximum is 1./ Integral of funciton in range and not 1 !<commit_after>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

/** \class RooCBShape
    \ingroup Roofit

PDF implementing the Crystal Ball line shape.
**/

#include "RooCBShape.h"

#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooMath.h"
#include "BatchHelpers.h"
#include "RooVDTHeaders.h"

#include "TMath.h"

#include <cmath>

using namespace std;

ClassImp(RooCBShape);

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::ApproxErf(Double_t arg) const
{
  static const double erflim = 5.0;
  if( arg > erflim )
    return 1.0;
  if( arg < -erflim )
    return -1.0;

  return RooMath::erf(arg);
}

////////////////////////////////////////////////////////////////////////////////

RooCBShape::RooCBShape(const char *name, const char *title,
             RooAbsReal& _m, RooAbsReal& _m0, RooAbsReal& _sigma,
             RooAbsReal& _alpha, RooAbsReal& _n) :
  RooAbsPdf(name, title),
  m("m", "Dependent", this, _m),
  m0("m0", "M0", this, _m0),
  sigma("sigma", "Sigma", this, _sigma),
  alpha("alpha", "Alpha", this, _alpha),
  n("n", "Order", this, _n)
{
}

////////////////////////////////////////////////////////////////////////////////

RooCBShape::RooCBShape(const RooCBShape& other, const char* name) :
  RooAbsPdf(other, name), m("m", this, other.m), m0("m0", this, other.m0),
  sigma("sigma", this, other.sigma), alpha("alpha", this, other.alpha),
  n("n", this, other.n)
{
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::evaluate() const {
  Double_t t = (m-m0)/sigma;
  if (alpha < 0) t = -t;

  Double_t absAlpha = fabs((Double_t)alpha);

  if (t >= -absAlpha) {
    return exp(-0.5*t*t);
  }
  else {
    Double_t a =  TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    Double_t b= n/absAlpha - absAlpha;

    return a/TMath::Power(b - t, n);
  }
}

////////////////////////////////////////////////////////////////////////////////

namespace {
//Author: Emmanouil Michalainas, CERN 21 August 2019

template<class Tm, class Tm0, class Tsigma, class Talpha, class Tn>
void compute(	size_t batchSize,
	double * __restrict output,
	Tm M, Tm0 M0, Tsigma S, Talpha A, Tn N)
{
  for (size_t i=0; i<batchSize; i++) {
    const double t = (M[i]-M0[i]) / S[i];
    if ((A[i]>0 && t>=-A[i])   ||   (A[i]<0 && -t>=A[i])) {
      output[i] = -0.5*t*t;
    } else {
      output[i] = N[i] / (N[i] -A[i]*A[i] -A[i]*t);
      output[i] = _rf_fast_log(output[i]);
      output[i] *= N[i];
      output[i] -= 0.5*A[i]*A[i];
    }
  }

  for (size_t i=0; i<batchSize; i++) {
    output[i] = _rf_fast_exp(output[i]);
  }
}
};

RooSpan<double> RooCBShape::evaluateBatch(std::size_t begin, std::size_t batchSize) const {
  using namespace BatchHelpers;

  EvaluateInfo info = getInfo( {&m, &m0, &sigma, &alpha, &n}, begin, batchSize );
  if (info.nBatches == 0) {
    return {};
  }
  auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
  auto mData = m.getValBatch(begin, info.size);

  if (info.nBatches==1 && !mData.empty()) {
    compute(info.size, output.data(), mData.data(),
    BracketAdapter<double> (m0),
    BracketAdapter<double> (sigma),
    BracketAdapter<double> (alpha),
    BracketAdapter<double> (n));
  }
  else {
    compute(info.size, output.data(),
    BracketAdapterWithMask (m,m.getValBatch(begin,info.size)),
    BracketAdapterWithMask (m0,m0.getValBatch(begin,info.size)),
    BracketAdapterWithMask (sigma,sigma.getValBatch(begin,info.size)),
    BracketAdapterWithMask (alpha,alpha.getValBatch(begin,info.size)),
    BracketAdapterWithMask (n,n.getValBatch(begin,info.size)));
  }
  return output;
}

////////////////////////////////////////////////////////////////////////////////

Int_t RooCBShape::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
{
  if( matchArgs(allVars,analVars,m) )
    return 1 ;

  return 0;
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::analyticalIntegral(Int_t code, const char* rangeName) const
{
  static const double sqrtPiOver2 = 1.2533141373;
  static const double sqrt2 = 1.4142135624;

  R__ASSERT(code==1);
  double result = 0.0;
  bool useLog = false;

  if( fabs(n-1.0) < 1.0e-05 )
    useLog = true;

  double sig = fabs((Double_t)sigma);

  double tmin = (m.min(rangeName)-m0)/sig;
  double tmax = (m.max(rangeName)-m0)/sig;

  if(alpha < 0) {
    double tmp = tmin;
    tmin = -tmax;
    tmax = -tmp;
  }

  double absAlpha = fabs((Double_t)alpha);

  if( tmin >= -absAlpha ) {
    result += sig*sqrtPiOver2*(   ApproxErf(tmax/sqrt2)
                                - ApproxErf(tmin/sqrt2) );
  }
  else if( tmax <= -absAlpha ) {
    double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    double b = n/absAlpha - absAlpha;

    if(useLog) {
      result += a*sig*( log(b-tmin) - log(b-tmax) );
    }
    else {
      result += a*sig/(1.0-n)*(   1.0/(TMath::Power(b-tmin,n-1.0))
                                - 1.0/(TMath::Power(b-tmax,n-1.0)) );
    }
  }
  else {
    double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
    double b = n/absAlpha - absAlpha;

    double term1 = 0.0;
    if(useLog) {
      term1 = a*sig*(  log(b-tmin) - log(n/absAlpha));
    }
    else {
      term1 = a*sig/(1.0-n)*(   1.0/(TMath::Power(b-tmin,n-1.0))
                              - 1.0/(TMath::Power(n/absAlpha,n-1.0)) );
    }

    double term2 = sig*sqrtPiOver2*(   ApproxErf(tmax/sqrt2)
                                     - ApproxErf(-absAlpha/sqrt2) );

    result += term1 + term2;
  }

  return result != 0. ? result : 1.E-300;
}

////////////////////////////////////////////////////////////////////////////////
/// Advertise that we know the maximum of self for given (m0,alpha,n,sigma)

Int_t RooCBShape::getMaxVal(const RooArgSet& vars) const
{
   RooArgSet dummy ;

  if (matchArgs(vars,dummy,m)) {
     return 1 ;
   }
  return 0 ;
}

////////////////////////////////////////////////////////////////////////////////

Double_t RooCBShape::maxVal(Int_t code) const
{
  R__ASSERT(code==1) ;

  // The maximum value for given (m0,alpha,n,sigma)
  // is 1./ Integral in the variable range
  return 1.0/analyticalIntegral(1) ;
}
<|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/sync/signin_manager.h"

#include "base/command_line.h"
#include "base/string_util.h"
#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/util/oauth.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"

const char kGetInfoEmailKey[] = "email";

SigninManager::SigninManager()
    : profile_(NULL), had_two_factor_error_(false) {}

SigninManager::~SigninManager() {}

// static
void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
  user_prefs->RegisterBooleanPref(prefs::kSyncUsingOAuth,
                                  "",
                                  PrefService::UNSYNCABLE_PREF);
  user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername,
                                 "",
                                 PrefService::UNSYNCABLE_PREF);
  user_prefs->RegisterBooleanPref(prefs::kAutologinEnabled,
                                  true,
                                  PrefService::UNSYNCABLE_PREF);
}

void SigninManager::Initialize(Profile* profile) {
  profile_ = profile;
  SetUsername(profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
  profile_->GetTokenService()->Initialize(
      GaiaConstants::kChromeSource, profile_);
  if (!GetUsername().empty()) {
    profile_->GetTokenService()->LoadTokensFromDB();
  }
}

bool SigninManager::IsInitialized() const {
  return profile_ != NULL;
}

void SigninManager::CleanupNotificationRegistration() {
#if !defined(OS_CHROMEOS)
  Source<TokenService> token_service(profile_->GetTokenService());
  if (registrar_.IsRegistered(this,
                              chrome::NOTIFICATION_TOKEN_AVAILABLE,
                              token_service)) {
    registrar_.Remove(this,
                      chrome::NOTIFICATION_TOKEN_AVAILABLE,
                      token_service);
  }
#endif
}

// If a username already exists, the user is logged in.
const std::string& SigninManager::GetUsername() {
  return browser_sync::IsUsingOAuth() ? oauth_username_ : username_;
}

void SigninManager::SetUsername(const std::string& username) {
  if (browser_sync::IsUsingOAuth())
    oauth_username_ = username;
  else
    username_ = username;
}

// static
void SigninManager::PrepareForSignin() {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(username_.empty());
#if !defined(OS_CHROMEOS)
  // The Sign out should clear the token service credentials.
  // Note: In CHROMEOS we might have valid credentials but still need to
  // set up 2-factor authentication.
  DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
#endif
}

// static
void SigninManager::PrepareForOAuthSignin() {
  DCHECK(browser_sync::IsUsingOAuth());
  DCHECK(oauth_username_.empty());
#if !defined(OS_CHROMEOS)
  // The Sign out should clear the token service credentials.
  // Note: In CHROMEOS we might have valid credentials but still need to
  // set up 2-factor authentication.
  DCHECK(!profile_->GetTokenService()->AreOAuthCredentialsValid());
#endif
}

// Users must always sign out before they sign in again.
void SigninManager::StartOAuthSignIn() {
  DCHECK(browser_sync::IsUsingOAuth());
  PrepareForOAuthSignin();
  oauth_login_.reset(new GaiaOAuthFetcher(this,
                                          profile_->GetRequestContext(),
                                          profile_,
                                          GaiaConstants::kSyncServiceOAuth));
  oauth_login_->StartGetOAuthToken();
  // TODO(rogerta?): Bug 92325: Expand Autologin to include OAuth signin
}

// Users must always sign out before they sign in again.
void SigninManager::StartSignIn(const std::string& username,
                                const std::string& password,
                                const std::string& login_token,
                                const std::string& login_captcha) {
  DCHECK(!browser_sync::IsUsingOAuth());
  PrepareForSignin();
  username_.assign(username);
  password_.assign(password);

  client_login_.reset(new GaiaAuthFetcher(this,
                                          GaiaConstants::kChromeSource,
                                          profile_->GetRequestContext()));
  client_login_->StartClientLogin(username,
                                  password,
                                  "",
                                  login_token,
                                  login_captcha,
                                  GaiaAuthFetcher::HostedAccountsNotAllowed);

  // Register for token availability.  The signin manager will pre-login the
  // user when the GAIA service token is ready for use.  Only do this if we
  // are not running in ChomiumOS, since it handles pre-login itself.
#if !defined(OS_CHROMEOS)
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin) &&
      profile_->GetPrefs()->GetBoolean(prefs::kAutologinEnabled)) {
    registrar_.Add(this,
                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
                   Source<TokenService>(profile_->GetTokenService()));
  }
#endif
}

void SigninManager::ProvideSecondFactorAccessCode(
    const std::string& access_code) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(!username_.empty() && !password_.empty() &&
      last_result_.data.empty());

  client_login_.reset(new GaiaAuthFetcher(this,
                                          GaiaConstants::kChromeSource,
                                          profile_->GetRequestContext()));
  client_login_->StartClientLogin(username_,
                                  access_code,
                                  "",
                                  std::string(),
                                  std::string(),
                                  GaiaAuthFetcher::HostedAccountsNotAllowed);
}

void SigninManager::SignOut() {
  if (!profile_)
    return;

  CleanupNotificationRegistration();

  client_login_.reset();
  last_result_ = ClientLoginResult();
  username_.clear();
  oauth_username_.clear();
  password_.clear();
  had_two_factor_error_ = false;
  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
  profile_->GetPrefs()->ClearPref(prefs::kSyncUsingOAuth);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();
  profile_->GetTokenService()->ResetCredentialsInMemory();
  profile_->GetTokenService()->EraseTokensFromDB();
}

void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
  DCHECK(!browser_sync::IsUsingOAuth());
  last_result_ = result;
  // Make a request for the canonical email address.
  client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey);
}

// NOTE: GetUserInfo is a ClientLogin request similar to OAuth's userinfo
void SigninManager::OnGetUserInfoSuccess(const std::string& key,
                                         const std::string& value) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(key == kGetInfoEmailKey);

  username_ = value;
  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
  profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, false);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();

  GoogleServiceSigninSuccessDetails details(username_, password_);
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
      Source<Profile>(profile_),
      Details<const GoogleServiceSigninSuccessDetails>(&details));

  password_.clear();  // Don't need it anymore.

  profile_->GetTokenService()->UpdateCredentials(last_result_);
  DCHECK(profile_->GetTokenService()->AreCredentialsValid());
  profile_->GetTokenService()->StartFetchingTokens();
}

void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(key == kGetInfoEmailKey);
  LOG(ERROR) << "Account is not associated with a valid email address. "
             << "Login failed.";
  OnClientLoginFailure(GoogleServiceAuthError(
      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}

void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
  LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
  OnClientLoginFailure(error);
}

void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
#if !defined(OS_CHROMEOS)
  VLOG(1) << "Unable to retrieve the token auth.";
  CleanupNotificationRegistration();
#endif
}

void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
      Source<Profile>(profile_),
      Details<const GoogleServiceAuthError>(&error));

  // We don't sign-out if the password was valid and we're just dealing with
  // a second factor error, and we don't sign out if we're dealing with
  // an invalid access code (again, because the password was valid).
  bool invalid_gaia = error.state() ==
      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
  if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
      (had_two_factor_error_ && invalid_gaia)) {
    had_two_factor_error_ = true;
    return;
  }

  SignOut();
}

void SigninManager::OnGetOAuthTokenSuccess(const std::string& oauth_token) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::SigninManager::OnGetOAuthTokenSuccess";
}

void SigninManager::OnGetOAuthTokenFailure(
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnGetOAuthTokenFailure";
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
      Source<Profile>(profile_),
      Details<const GoogleServiceAuthError>(&error));
  SignOut();
}

void SigninManager::OnOAuthGetAccessTokenSuccess(const std::string& token,
                                                 const std::string& secret) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::OnOAuthGetAccessTokenSuccess";
  profile_->GetTokenService()->UpdateOAuthCredentials(token, secret);
}

void SigninManager::OnOAuthGetAccessTokenFailure(
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnOAuthGetAccessTokenFailure";
}

void SigninManager::OnOAuthWrapBridgeSuccess(const std::string& service_name,
                                             const std::string& token,
                                             const std::string& expires_in) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::OnOAuthWrapBridgeSuccess";
}

void SigninManager::OnOAuthWrapBridgeFailure(
    const std::string& service_scope,
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnOAuthWrapBridgeFailure";
}

// NOTE: userinfo is an OAuth request similar to ClientLogin's GetUserInfo
void SigninManager::OnUserInfoSuccess(const std::string& email) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "Sync signin for " << email << " is complete.";
  oauth_username_ = email;
  profile_->GetPrefs()->SetString(
      prefs::kGoogleServicesUsername, oauth_username_);
  profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, true);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();

  DCHECK(password_.empty());
  GoogleServiceSigninSuccessDetails details(oauth_username_, "");
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
      Source<Profile>(profile_),
      Details<const GoogleServiceSigninSuccessDetails>(&details));

  DCHECK(profile_->GetTokenService()->AreOAuthCredentialsValid());
  profile_->GetTokenService()->StartFetchingOAuthTokens();
}

void SigninManager::OnUserInfoFailure(const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnUserInfoFailure";
}

void SigninManager::Observe(int type,
                            const NotificationSource& source,
                            const NotificationDetails& details) {
#if !defined(OS_CHROMEOS)
  DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
  TokenService::TokenAvailableDetails* tok_details =
      Details<TokenService::TokenAvailableDetails>(details).ptr();

  // If a GAIA service token has become available, use it to pre-login the
  // user to other services that depend on GAIA credentials.
  if (tok_details->service() == GaiaConstants::kGaiaService) {
    DCHECK(!browser_sync::IsUsingOAuth());
    if (client_login_.get() == NULL) {
      client_login_.reset(new GaiaAuthFetcher(this,
                                              GaiaConstants::kChromeSource,
                                              profile_->GetRequestContext()));
    }

    client_login_->StartMergeSession(tok_details->token());

    // We only want to do this once per sign-in.
    CleanupNotificationRegistration();
  }
#endif
}
<commit_msg>Adding explicit CHECK to highlight crashes for profiles where the TokenService is NULL.<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/sync/signin_manager.h"

#include "base/command_line.h"
#include "base/string_util.h"
#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/util/oauth.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"

const char kGetInfoEmailKey[] = "email";

SigninManager::SigninManager()
    : profile_(NULL), had_two_factor_error_(false) {}

SigninManager::~SigninManager() {}

// static
void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
  user_prefs->RegisterBooleanPref(prefs::kSyncUsingOAuth,
                                  "",
                                  PrefService::UNSYNCABLE_PREF);
  user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername,
                                 "",
                                 PrefService::UNSYNCABLE_PREF);
  user_prefs->RegisterBooleanPref(prefs::kAutologinEnabled,
                                  true,
                                  PrefService::UNSYNCABLE_PREF);
}

void SigninManager::Initialize(Profile* profile) {
  profile_ = profile;
  SetUsername(profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
  profile_->GetTokenService()->Initialize(
      GaiaConstants::kChromeSource, profile_);
  if (!GetUsername().empty()) {
    profile_->GetTokenService()->LoadTokensFromDB();
  }
}

bool SigninManager::IsInitialized() const {
  return profile_ != NULL;
}

void SigninManager::CleanupNotificationRegistration() {
#if !defined(OS_CHROMEOS)
  Source<TokenService> token_service(profile_->GetTokenService());
  if (registrar_.IsRegistered(this,
                              chrome::NOTIFICATION_TOKEN_AVAILABLE,
                              token_service)) {
    registrar_.Remove(this,
                      chrome::NOTIFICATION_TOKEN_AVAILABLE,
                      token_service);
  }
#endif
}

// If a username already exists, the user is logged in.
const std::string& SigninManager::GetUsername() {
  return browser_sync::IsUsingOAuth() ? oauth_username_ : username_;
}

void SigninManager::SetUsername(const std::string& username) {
  if (browser_sync::IsUsingOAuth())
    oauth_username_ = username;
  else
    username_ = username;
}

// static
void SigninManager::PrepareForSignin() {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(username_.empty());
#if !defined(OS_CHROMEOS)
  // The Sign out should clear the token service credentials.
  // Note: In CHROMEOS we might have valid credentials but still need to
  // set up 2-factor authentication.
  DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
#endif
}

// static
void SigninManager::PrepareForOAuthSignin() {
  DCHECK(browser_sync::IsUsingOAuth());
  DCHECK(oauth_username_.empty());
#if !defined(OS_CHROMEOS)
  // The Sign out should clear the token service credentials.
  // Note: In CHROMEOS we might have valid credentials but still need to
  // set up 2-factor authentication.
  DCHECK(!profile_->GetTokenService()->AreOAuthCredentialsValid());
#endif
}

// Users must always sign out before they sign in again.
void SigninManager::StartOAuthSignIn() {
  DCHECK(browser_sync::IsUsingOAuth());
  PrepareForOAuthSignin();
  oauth_login_.reset(new GaiaOAuthFetcher(this,
                                          profile_->GetRequestContext(),
                                          profile_,
                                          GaiaConstants::kSyncServiceOAuth));
  oauth_login_->StartGetOAuthToken();
  // TODO(rogerta?): Bug 92325: Expand Autologin to include OAuth signin
}

// Users must always sign out before they sign in again.
void SigninManager::StartSignIn(const std::string& username,
                                const std::string& password,
                                const std::string& login_token,
                                const std::string& login_captcha) {
  DCHECK(!browser_sync::IsUsingOAuth());
  PrepareForSignin();
  username_.assign(username);
  password_.assign(password);

  client_login_.reset(new GaiaAuthFetcher(this,
                                          GaiaConstants::kChromeSource,
                                          profile_->GetRequestContext()));
  client_login_->StartClientLogin(username,
                                  password,
                                  "",
                                  login_token,
                                  login_captcha,
                                  GaiaAuthFetcher::HostedAccountsNotAllowed);

  // Register for token availability.  The signin manager will pre-login the
  // user when the GAIA service token is ready for use.  Only do this if we
  // are not running in ChomiumOS, since it handles pre-login itself.
#if !defined(OS_CHROMEOS)
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin) &&
      profile_->GetPrefs()->GetBoolean(prefs::kAutologinEnabled)) {
    registrar_.Add(this,
                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
                   Source<TokenService>(profile_->GetTokenService()));
  }
#endif
}

void SigninManager::ProvideSecondFactorAccessCode(
    const std::string& access_code) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(!username_.empty() && !password_.empty() &&
      last_result_.data.empty());

  client_login_.reset(new GaiaAuthFetcher(this,
                                          GaiaConstants::kChromeSource,
                                          profile_->GetRequestContext()));
  client_login_->StartClientLogin(username_,
                                  access_code,
                                  "",
                                  std::string(),
                                  std::string(),
                                  GaiaAuthFetcher::HostedAccountsNotAllowed);
}

void SigninManager::SignOut() {
  if (!profile_)
    return;

  CleanupNotificationRegistration();

  client_login_.reset();
  last_result_ = ClientLoginResult();
  username_.clear();
  oauth_username_.clear();
  password_.clear();
  had_two_factor_error_ = false;
  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
  profile_->GetPrefs()->ClearPref(prefs::kSyncUsingOAuth);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();
  profile_->GetTokenService()->ResetCredentialsInMemory();
  profile_->GetTokenService()->EraseTokensFromDB();
}

void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
  DCHECK(!browser_sync::IsUsingOAuth());
  last_result_ = result;
  // Make a request for the canonical email address.
  client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey);
}

// NOTE: GetUserInfo is a ClientLogin request similar to OAuth's userinfo
void SigninManager::OnGetUserInfoSuccess(const std::string& key,
                                         const std::string& value) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(key == kGetInfoEmailKey);

  username_ = value;
  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
  profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, false);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();

  GoogleServiceSigninSuccessDetails details(username_, password_);
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
      Source<Profile>(profile_),
      Details<const GoogleServiceSigninSuccessDetails>(&details));

  password_.clear();  // Don't need it anymore.

  profile_->GetTokenService()->UpdateCredentials(last_result_);
  DCHECK(profile_->GetTokenService()->AreCredentialsValid());
  profile_->GetTokenService()->StartFetchingTokens();
}

void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
  DCHECK(!browser_sync::IsUsingOAuth());
  DCHECK(key == kGetInfoEmailKey);
  LOG(ERROR) << "Account is not associated with a valid email address. "
             << "Login failed.";
  OnClientLoginFailure(GoogleServiceAuthError(
      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}

void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
  LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
  OnClientLoginFailure(error);
}

void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
#if !defined(OS_CHROMEOS)
  VLOG(1) << "Unable to retrieve the token auth.";
  CleanupNotificationRegistration();
#endif
}

void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
  DCHECK(!browser_sync::IsUsingOAuth());
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
      Source<Profile>(profile_),
      Details<const GoogleServiceAuthError>(&error));

  // We don't sign-out if the password was valid and we're just dealing with
  // a second factor error, and we don't sign out if we're dealing with
  // an invalid access code (again, because the password was valid).
  bool invalid_gaia = error.state() ==
      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
  if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
      (had_two_factor_error_ && invalid_gaia)) {
    had_two_factor_error_ = true;
    return;
  }

  SignOut();
}

void SigninManager::OnGetOAuthTokenSuccess(const std::string& oauth_token) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::SigninManager::OnGetOAuthTokenSuccess";
}

void SigninManager::OnGetOAuthTokenFailure(
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnGetOAuthTokenFailure";
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
      Source<Profile>(profile_),
      Details<const GoogleServiceAuthError>(&error));
  SignOut();
}

void SigninManager::OnOAuthGetAccessTokenSuccess(const std::string& token,
                                                 const std::string& secret) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::OnOAuthGetAccessTokenSuccess";
  profile_->GetTokenService()->UpdateOAuthCredentials(token, secret);
}

void SigninManager::OnOAuthGetAccessTokenFailure(
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnOAuthGetAccessTokenFailure";
}

void SigninManager::OnOAuthWrapBridgeSuccess(const std::string& service_name,
                                             const std::string& token,
                                             const std::string& expires_in) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "SigninManager::OnOAuthWrapBridgeSuccess";
}

void SigninManager::OnOAuthWrapBridgeFailure(
    const std::string& service_scope,
    const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnOAuthWrapBridgeFailure";
}

// NOTE: userinfo is an OAuth request similar to ClientLogin's GetUserInfo
void SigninManager::OnUserInfoSuccess(const std::string& email) {
  DCHECK(browser_sync::IsUsingOAuth());
  VLOG(1) << "Sync signin for " << email << " is complete.";
  oauth_username_ = email;
  profile_->GetPrefs()->SetString(
      prefs::kGoogleServicesUsername, oauth_username_);
  profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, true);
  profile_->GetPrefs()->ScheduleSavePersistentPrefs();

  DCHECK(password_.empty());
  GoogleServiceSigninSuccessDetails details(oauth_username_, "");
  NotificationService::current()->Notify(
      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
      Source<Profile>(profile_),
      Details<const GoogleServiceSigninSuccessDetails>(&details));

  TokenService* token_service = profile_->GetTokenService();
  CHECK(token_service);
  DCHECK(token_service->AreOAuthCredentialsValid());
  token_service->StartFetchingOAuthTokens();
}

void SigninManager::OnUserInfoFailure(const GoogleServiceAuthError& error) {
  DCHECK(browser_sync::IsUsingOAuth());
  LOG(WARNING) << "SigninManager::OnUserInfoFailure";
}

void SigninManager::Observe(int type,
                            const NotificationSource& source,
                            const NotificationDetails& details) {
#if !defined(OS_CHROMEOS)
  DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
  TokenService::TokenAvailableDetails* tok_details =
      Details<TokenService::TokenAvailableDetails>(details).ptr();

  // If a GAIA service token has become available, use it to pre-login the
  // user to other services that depend on GAIA credentials.
  if (tok_details->service() == GaiaConstants::kGaiaService) {
    DCHECK(!browser_sync::IsUsingOAuth());
    if (client_login_.get() == NULL) {
      client_login_.reset(new GaiaAuthFetcher(this,
                                              GaiaConstants::kChromeSource,
                                              profile_->GetRequestContext()));
    }

    client_login_->StartMergeSession(tok_details->token());

    // We only want to do this once per sign-in.
    CleanupNotificationRegistration();
  }
#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 <algorithm>

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/sha1.h"
#include "base/singleton.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/service_process_util.h"
#include "content/common/child_process_host.h"

#if !defined(OS_MACOSX)

namespace {

// This should be more than enough to hold a version string assuming each part
// of the version string is an int64.
const uint32 kMaxVersionStringLength = 256;

// The structure that gets written to shared memory.
struct ServiceProcessSharedData {
  char service_process_version[kMaxVersionStringLength];
  base::ProcessId service_process_pid;
};

// Gets the name of the shared memory used by the service process to write its
// version. The name is not versioned.
std::string GetServiceProcessSharedMemName() {
  return GetServiceProcessScopedName("_service_shmem");
}

enum ServiceProcessRunningState {
  SERVICE_NOT_RUNNING,
  SERVICE_OLDER_VERSION_RUNNING,
  SERVICE_SAME_VERSION_RUNNING,
  SERVICE_NEWER_VERSION_RUNNING,
};

ServiceProcessRunningState GetServiceProcessRunningState(
    std::string* service_version_out, base::ProcessId* pid_out) {
  std::string version;
  if (!GetServiceProcessData(&version, pid_out))
    return SERVICE_NOT_RUNNING;

#if defined(OS_POSIX)
  // We only need to check for service running on POSIX because Windows cleans
  // up shared memory files when an app crashes, so there isn't a chance of
  // us reading bogus data from shared memory for an app that has died.
  if (!CheckServiceProcessReady()) {
    return SERVICE_NOT_RUNNING;
  }
#endif  // defined(OS_POSIX)

  // At this time we have a version string. Set the out param if it exists.
  if (service_version_out)
    *service_version_out = version;

  scoped_ptr<Version> service_version(Version::GetVersionFromString(version));
  // If the version string is invalid, treat it like an older version.
  if (!service_version.get())
    return SERVICE_OLDER_VERSION_RUNNING;

  // Get the version of the currently *running* instance of Chrome.
  chrome::VersionInfo version_info;
  if (!version_info.is_valid()) {
    NOTREACHED() << "Failed to get current file version";
    // Our own version is invalid. This is an error case. Pretend that we
    // are out of date.
    return SERVICE_NEWER_VERSION_RUNNING;
  }
  scoped_ptr<Version> running_version(Version::GetVersionFromString(
      version_info.Version()));
  if (!running_version.get()) {
    NOTREACHED() << "Failed to parse version info";
    // Our own version is invalid. This is an error case. Pretend that we
    // are out of date.
    return SERVICE_NEWER_VERSION_RUNNING;
  }

  if (running_version->CompareTo(*service_version) > 0) {
    return SERVICE_OLDER_VERSION_RUNNING;
  } else if (service_version->CompareTo(*running_version) > 0) {
    return SERVICE_NEWER_VERSION_RUNNING;
  }
  return SERVICE_SAME_VERSION_RUNNING;
}

}  // namespace

// Return a name that is scoped to this instance of the service process. We
// use the hash of the user-data-dir as a scoping prefix. We can't use
// the user-data-dir itself as we have limits on the size of the lock names.
std::string GetServiceProcessScopedName(const std::string& append_str) {
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
#if defined(OS_WIN)
  std::string user_data_dir_path = WideToUTF8(user_data_dir.value());
#elif defined(OS_POSIX)
  std::string user_data_dir_path = user_data_dir.value();
#endif  // defined(OS_WIN)
  std::string hash = base::SHA1HashString(user_data_dir_path);
  std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
  return hex_hash + "." + append_str;
}

// Return a name that is scoped to this instance of the service process. We
// use the user-data-dir and the version as a scoping prefix.
std::string GetServiceProcessScopedVersionedName(
    const std::string& append_str) {
  std::string versioned_str;
  chrome::VersionInfo version_info;
  DCHECK(version_info.is_valid());
  versioned_str.append(version_info.Version());
  versioned_str.append(append_str);
  return GetServiceProcessScopedName(versioned_str);
}

// Reads the named shared memory to get the shared data. Returns false if no
// matching shared memory was found.
bool GetServiceProcessData(std::string* version, base::ProcessId* pid) {
  scoped_ptr<base::SharedMemory> shared_mem_service_data;
  shared_mem_service_data.reset(new base::SharedMemory());
  ServiceProcessSharedData* service_data = NULL;
  if (shared_mem_service_data.get() &&
      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
    service_data = reinterpret_cast<ServiceProcessSharedData*>(
        shared_mem_service_data->memory());
    // Make sure the version in shared memory is null-terminated. If it is not,
    // treat it as invalid.
    if (version && memchr(service_data->service_process_version, '\0',
                          sizeof(service_data->service_process_version)))
      *version = service_data->service_process_version;
    if (pid)
      *pid = service_data->service_process_pid;
    return true;
  }
  return false;
}

// Gets the name of the service process IPC channel.
IPC::ChannelHandle GetServiceProcessChannel() {
  return GetServiceProcessScopedVersionedName("_service_ipc");
}

#endif  // !OS_MACOSX

ServiceProcessState::ServiceProcessState() : state_(NULL) {
  CreateAutoRunCommandLine();
}

ServiceProcessState::~ServiceProcessState() {
#if !defined(OS_MACOSX)
  if (shared_mem_service_data_.get()) {
    shared_mem_service_data_->Delete(GetServiceProcessSharedMemName());
  }
#endif  // !OS_MACOSX
  TearDownState();
}

// static
ServiceProcessState* ServiceProcessState::GetInstance() {
  return Singleton<ServiceProcessState>::get();
}

void ServiceProcessState::SignalStopped() {
  TearDownState();
  shared_mem_service_data_.reset();
}

#if !defined(OS_MACOSX)
bool ServiceProcessState::Initialize() {
  if (!CreateState()) {
    return false;
  }
  if (!TakeSingletonLock()) {
    return false;
  }
  // Now that we have the singleton, take care of killing an older version, if
  // it exists.
  if (!HandleOtherVersion())
    return false;

  // Write the version we are using to shared memory. This can be used by a
  // newer service to signal us to exit.
  return CreateSharedData();
}

bool ServiceProcessState::HandleOtherVersion() {
  std::string running_version;
  base::ProcessId process_id;
  ServiceProcessRunningState state =
      GetServiceProcessRunningState(&running_version, &process_id);
  switch (state) {
    case SERVICE_SAME_VERSION_RUNNING:
    case SERVICE_NEWER_VERSION_RUNNING:
      return false;
    case SERVICE_OLDER_VERSION_RUNNING:
      // If an older version is running, kill it.
      ForceServiceProcessShutdown(running_version, process_id);
      break;
    case SERVICE_NOT_RUNNING:
      break;
  }
  return true;
}

bool ServiceProcessState::CreateSharedData() {
  chrome::VersionInfo version_info;
  if (!version_info.is_valid()) {
    NOTREACHED() << "Failed to get current file version";
    return false;
  }
  if (version_info.Version().length() >= kMaxVersionStringLength) {
    NOTREACHED() << "Version string length is << " <<
        version_info.Version().length() << "which is longer than" <<
        kMaxVersionStringLength;
    return false;
  }

  scoped_ptr<base::SharedMemory> shared_mem_service_data(
      new base::SharedMemory());
  if (!shared_mem_service_data.get())
    return false;

  uint32 alloc_size = sizeof(ServiceProcessSharedData);
  if (!shared_mem_service_data->CreateNamed(GetServiceProcessSharedMemName(),
                                            true, alloc_size))
    return false;

  if (!shared_mem_service_data->Map(alloc_size))
    return false;

  memset(shared_mem_service_data->memory(), 0, alloc_size);
  ServiceProcessSharedData* shared_data =
      reinterpret_cast<ServiceProcessSharedData*>(
          shared_mem_service_data->memory());
  memcpy(shared_data->service_process_version, version_info.Version().c_str(),
         version_info.Version().length());
  shared_data->service_process_pid = base::GetCurrentProcId();
  shared_mem_service_data_.reset(shared_mem_service_data.release());
  return true;
}

IPC::ChannelHandle ServiceProcessState::GetServiceProcessChannel() {
  return ::GetServiceProcessChannel();
}

#endif  // !OS_MACOSX

void ServiceProcessState::CreateAutoRunCommandLine() {
  FilePath exe_path = ChildProcessHost::GetChildPath(false);
  if (exe_path.empty()) {
    NOTREACHED() << "Unable to get service process binary name.";
  }
  autorun_command_line_.reset(new CommandLine(exe_path));
  autorun_command_line_->AppendSwitchASCII(switches::kProcessType,
                                           switches::kServiceProcess);

  // The user data directory is the only other flag we currently want to
  // possibly store.
  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  FilePath user_data_dir =
    browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
  if (!user_data_dir.empty())
    autorun_command_line_->AppendSwitchPath(switches::kUserDataDir,
                                            user_data_dir);
}
<commit_msg>Committing on behalf of asharif1@chromium.org.<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 <algorithm>

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/sha1.h"
#include "base/singleton.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/service_process_util.h"
#include "content/common/child_process_host.h"

#if !defined(OS_MACOSX)

namespace {

// This should be more than enough to hold a version string assuming each part
// of the version string is an int64.
const uint32 kMaxVersionStringLength = 256;

// The structure that gets written to shared memory.
struct ServiceProcessSharedData {
  char service_process_version[kMaxVersionStringLength];
  base::ProcessId service_process_pid;
};

// Gets the name of the shared memory used by the service process to write its
// version. The name is not versioned.
std::string GetServiceProcessSharedMemName() {
  return GetServiceProcessScopedName("_service_shmem");
}

enum ServiceProcessRunningState {
  SERVICE_NOT_RUNNING,
  SERVICE_OLDER_VERSION_RUNNING,
  SERVICE_SAME_VERSION_RUNNING,
  SERVICE_NEWER_VERSION_RUNNING,
};

ServiceProcessRunningState GetServiceProcessRunningState(
    std::string* service_version_out, base::ProcessId* pid_out) {
  std::string version;
  if (!GetServiceProcessData(&version, pid_out))
    return SERVICE_NOT_RUNNING;

#if defined(OS_POSIX)
  // We only need to check for service running on POSIX because Windows cleans
  // up shared memory files when an app crashes, so there isn't a chance of
  // us reading bogus data from shared memory for an app that has died.
  if (!CheckServiceProcessReady()) {
    return SERVICE_NOT_RUNNING;
  }
#endif  // defined(OS_POSIX)

  // At this time we have a version string. Set the out param if it exists.
  if (service_version_out)
    *service_version_out = version;

  scoped_ptr<Version> service_version(Version::GetVersionFromString(version));
  // If the version string is invalid, treat it like an older version.
  if (!service_version.get())
    return SERVICE_OLDER_VERSION_RUNNING;

  // Get the version of the currently *running* instance of Chrome.
  chrome::VersionInfo version_info;
  if (!version_info.is_valid()) {
    NOTREACHED() << "Failed to get current file version";
    // Our own version is invalid. This is an error case. Pretend that we
    // are out of date.
    return SERVICE_NEWER_VERSION_RUNNING;
  }
  scoped_ptr<Version> running_version(Version::GetVersionFromString(
      version_info.Version()));
  if (!running_version.get()) {
    NOTREACHED() << "Failed to parse version info";
    // Our own version is invalid. This is an error case. Pretend that we
    // are out of date.
    return SERVICE_NEWER_VERSION_RUNNING;
  }

  if (running_version->CompareTo(*service_version) > 0) {
    return SERVICE_OLDER_VERSION_RUNNING;
  } else if (service_version->CompareTo(*running_version) > 0) {
    return SERVICE_NEWER_VERSION_RUNNING;
  }
  return SERVICE_SAME_VERSION_RUNNING;
}

}  // namespace

// Return a name that is scoped to this instance of the service process. We
// use the hash of the user-data-dir as a scoping prefix. We can't use
// the user-data-dir itself as we have limits on the size of the lock names.
std::string GetServiceProcessScopedName(const std::string& append_str) {
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
#if defined(OS_WIN)
  std::string user_data_dir_path = WideToUTF8(user_data_dir.value());
#elif defined(OS_POSIX)
  std::string user_data_dir_path = user_data_dir.value();
#endif  // defined(OS_WIN)
  std::string hash = base::SHA1HashString(user_data_dir_path);
  std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
  return hex_hash + "." + append_str;
}

// Return a name that is scoped to this instance of the service process. We
// use the user-data-dir and the version as a scoping prefix.
std::string GetServiceProcessScopedVersionedName(
    const std::string& append_str) {
  std::string versioned_str;
  chrome::VersionInfo version_info;
  DCHECK(version_info.is_valid());
  versioned_str.append(version_info.Version());
  versioned_str.append(append_str);
  return GetServiceProcessScopedName(versioned_str);
}

// Reads the named shared memory to get the shared data. Returns false if no
// matching shared memory was found.
bool GetServiceProcessData(std::string* version, base::ProcessId* pid) {
  scoped_ptr<base::SharedMemory> shared_mem_service_data;
  shared_mem_service_data.reset(new base::SharedMemory());
  ServiceProcessSharedData* service_data = NULL;
  if (shared_mem_service_data.get() &&
      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
    service_data = reinterpret_cast<ServiceProcessSharedData*>(
        shared_mem_service_data->memory());
    // Make sure the version in shared memory is null-terminated. If it is not,
    // treat it as invalid.
    if (version && memchr(service_data->service_process_version, '\0',
                          sizeof(service_data->service_process_version)))
      *version = service_data->service_process_version;
    if (pid)
      *pid = service_data->service_process_pid;
    return true;
  }
  return false;
}

// Gets the name of the service process IPC channel.
IPC::ChannelHandle GetServiceProcessChannel() {
  return GetServiceProcessScopedVersionedName("_service_ipc");
}

#endif  // !OS_MACOSX

ServiceProcessState::ServiceProcessState() : state_(NULL) {
  CreateAutoRunCommandLine();
}

ServiceProcessState::~ServiceProcessState() {
#if !defined(OS_MACOSX)
  if (shared_mem_service_data_.get()) {
    shared_mem_service_data_->Delete(GetServiceProcessSharedMemName());
  }
#endif  // !OS_MACOSX
  TearDownState();
}

// static
ServiceProcessState* ServiceProcessState::GetInstance() {
  return Singleton<ServiceProcessState>::get();
}

void ServiceProcessState::SignalStopped() {
  TearDownState();
  shared_mem_service_data_.reset();
}

#if !defined(OS_MACOSX)
bool ServiceProcessState::Initialize() {
  if (!CreateState()) {
    return false;
  }
  if (!TakeSingletonLock()) {
    return false;
  }
  // Now that we have the singleton, take care of killing an older version, if
  // it exists.
  if (!HandleOtherVersion())
    return false;

  // Write the version we are using to shared memory. This can be used by a
  // newer service to signal us to exit.
  return CreateSharedData();
}

bool ServiceProcessState::HandleOtherVersion() {
  std::string running_version;
  base::ProcessId process_id = 0;
  ServiceProcessRunningState state =
      GetServiceProcessRunningState(&running_version, &process_id);
  switch (state) {
    case SERVICE_SAME_VERSION_RUNNING:
    case SERVICE_NEWER_VERSION_RUNNING:
      return false;
    case SERVICE_OLDER_VERSION_RUNNING:
      // If an older version is running, kill it.
      ForceServiceProcessShutdown(running_version, process_id);
      break;
    case SERVICE_NOT_RUNNING:
      break;
  }
  return true;
}

bool ServiceProcessState::CreateSharedData() {
  chrome::VersionInfo version_info;
  if (!version_info.is_valid()) {
    NOTREACHED() << "Failed to get current file version";
    return false;
  }
  if (version_info.Version().length() >= kMaxVersionStringLength) {
    NOTREACHED() << "Version string length is << " <<
        version_info.Version().length() << "which is longer than" <<
        kMaxVersionStringLength;
    return false;
  }

  scoped_ptr<base::SharedMemory> shared_mem_service_data(
      new base::SharedMemory());
  if (!shared_mem_service_data.get())
    return false;

  uint32 alloc_size = sizeof(ServiceProcessSharedData);
  if (!shared_mem_service_data->CreateNamed(GetServiceProcessSharedMemName(),
                                            true, alloc_size))
    return false;

  if (!shared_mem_service_data->Map(alloc_size))
    return false;

  memset(shared_mem_service_data->memory(), 0, alloc_size);
  ServiceProcessSharedData* shared_data =
      reinterpret_cast<ServiceProcessSharedData*>(
          shared_mem_service_data->memory());
  memcpy(shared_data->service_process_version, version_info.Version().c_str(),
         version_info.Version().length());
  shared_data->service_process_pid = base::GetCurrentProcId();
  shared_mem_service_data_.reset(shared_mem_service_data.release());
  return true;
}

IPC::ChannelHandle ServiceProcessState::GetServiceProcessChannel() {
  return ::GetServiceProcessChannel();
}

#endif  // !OS_MACOSX

void ServiceProcessState::CreateAutoRunCommandLine() {
  FilePath exe_path = ChildProcessHost::GetChildPath(false);
  if (exe_path.empty()) {
    NOTREACHED() << "Unable to get service process binary name.";
  }
  autorun_command_line_.reset(new CommandLine(exe_path));
  autorun_command_line_->AppendSwitchASCII(switches::kProcessType,
                                           switches::kServiceProcess);

  // The user data directory is the only other flag we currently want to
  // possibly store.
  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  FilePath user_data_dir =
    browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
  if (!user_data_dir.empty())
    autorun_command_line_->AppendSwitchPath(switches::kUserDataDir,
                                            user_data_dir);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Marcin Zdun
 *
 * 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 <stdio.h>
#include <string.h>

#include <memory>
#include <iostream>
#include <algorithm>
#include <map>

#include <scene.hpp>
#include <camera.hpp>
#include <block.hpp>

struct Command {
	const char* name;
	int (*command)(int, char* []);
	Command(const char* name, int (*command)(int, char* []))
		: name(name)
		, command(command)
	{}
	int run(int argc, char* argv[])
	{
		return command(argc, argv);
	}
};

template <size_t N>
Command* get_cmmd(Command (&commands)[N], int argc, char* argv[])
{
	if (argc > 1)
		for (size_t i = 0; i < N; ++i)
		{
			if (strcmp(argv[1], commands[i].name) == 0)
				return commands + i;
		}

		if (argc > 1)
			fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
		else
			fprintf(stderr, "%s: command missing\n", argv[0]);

		fprintf(stderr, "\nKnown commands are:\n");
		for (size_t i = 0; i < N; ++i)
			fprintf(stderr, "\t%s\n", commands[i].name);

		return nullptr;
}

int test(int, char* []);

Command commands[] = {
	Command("test", test)
};

int main(int argc, char* argv[])
{
	char prog[] = "studio";
	argv[0] = prog;
	Command* command = get_cmmd(commands, argc, argv);

	if (command == nullptr)
		return 1;

	return command->run(argc - 1, argv + 1);
}

using namespace studio;

int test(int argc, char* argv [])
{
	Scene scene;

	auto cam = scene.add<Camera>(math::Vertex(0, 500, -1000), math::Vertex(0, 500, 0));
	auto block = scene.add<Block>(100, 100, 100);

	scene.renderTo(cam.get());

	return 0;
}<commit_msg>Example app<commit_after>/*
 * Copyright (C) 2013 Marcin Zdun
 *
 * 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 <stdio.h>
#include <string.h>

#include <memory>
#include <iostream>
#include <algorithm>
#include <map>

#include <scene.hpp>
#include <camera.hpp>
#include <block.hpp>
#include <platform_api.hpp>
#include <canvas_types.hpp>

#include <future>
#include <iomanip>

#define STEREO_CANVAS

#if 1
typedef studio::CyanMagentaCanvas StereoCanvasType;
#else
typedef studio::SideBySideCanvas StereoCanvasType;
#endif

struct Command {
	const char* name;
	int (*command)(int, char* []);
	Command(const char* name, int (*command)(int, char* []))
		: name(name)
		, command(command)
	{}
	int run(int argc, char* argv[])
	{
		return command(argc, argv);
	}
};

template <size_t N>
Command* get_cmmd(Command (&commands)[N], int argc, char* argv[])
{
	if (argc > 1)
		for (size_t i = 0; i < N; ++i)
		{
			if (strcmp(argv[1], commands[i].name) == 0)
				return commands + i;
		}

		if (argc > 1)
			fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
		else
			fprintf(stderr, "%s: command missing\n", argv[0]);

		fprintf(stderr, "\nKnown commands are:\n");
		for (size_t i = 0; i < N; ++i)
			fprintf(stderr, "\t%s\n", commands[i].name);

		return nullptr;
}

int test(int, char* []);

Command commands[] = {
	Command("test", test)
};

int main(int argc, char* argv[])
{
	char prog[] = "studio";
	argv[0] = prog;
	Command* command = get_cmmd(commands, argc, argv);

	if (command == nullptr)
		return 1;

	return command->run(argc - 1, argv + 1);
}

using namespace studio;

void setUp(std::shared_ptr<Scene>& scene)
{
	scene->add<Block>(2015, 1235, 1);
	scene->add<Block>(2015, 1, 1060)->translate(0,    0,  -1060);
	scene->add<Block>(2015, 1, 1060)->translate(0, 1235,  -1060);

	scene->add<Block>(425, 300, 210)->translate(1365, 0,   -210);
	scene->add<Block>(425, 300, 210)->translate(940,  0,   -210);
	scene->add<Block>(425, 300, 210)->translate(515,  0,   -210);

	scene->add<Block>(225, 590, 210)->translate(1790, 0,   -210);
	scene->add<Block>(225, 590, 210)->translate(1790, 590, -210);

	scene->add<Block>(225, 780, 160)->translate(1565, 400, -160);
	scene->add<Block>(225, 590, 160)->translate(1340, 590, -160);

	scene->add<Block>(225, 590, 160)->translate(410,  590, -160);
	scene->add<Block>(225, 780, 160)->translate(185,  400, -160);

	scene->add<Block>(577, 352, 48)->translate(700, 545, -96);
}

std::shared_ptr<StereoCanvasType> g_canvas;

int test(int argc, char* argv [])
{
	PlatformAPI init;

	auto scene = std::make_shared<Scene>();
	setUp(scene);

	math::Vertex camPos { 1007.5, 617.5, -1000 };

#ifdef STEREO_CANVAS
	auto canvas = std::make_shared<StereoCanvasType>(1400, 800);
	g_canvas = canvas;
	auto cam = scene->add<StereoCamera>(1000, 50, camPos, camPos + math::Vertex(0, 0, 100));
	cam->setCanvas(canvas.get());
#else
	auto cam = scene->add<Camera>(1000, camPos, camPos + math::Vertex(0, 0, 100));
	auto canvas = cam->create_canvas<SimpleCanvas>(1400, 800);
#endif

	scene->renderAllCameras();
	canvas->save("test.png");

#if 0
	std::vector<std::future<void>> tasks;

	for (size_t id = 0; id < 25; ++id)
	{
		tasks.push_back(std::move(std::async([=](const math::Vertex& camPos){
			std::cout << "<" << std::flush;
			auto cam = scene->add<Camera>(1000, camPos + math::Vertex(50 * id, 0, 0), camPos + math::Vertex(50 * id, 0, 100));
			auto canvas = cam->create_canvas<BmpCanvas>(1400, 800);
			scene->renderTo(cam.get());

			wchar_t fname[100];
			swprintf_s(fname, L"test_%04d.png", id);
			canvas->save(fname, L"image/png");
			std::cout << ">" << std::flush;
		}, math::Vertex{ 507.5, 800, -1000 })));
	}

	for (auto && f : tasks)
		f.get();

	tasks.clear();
#endif

	g_canvas.reset();
	scene.reset();

	return 0;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: file_path_helper.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:55:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _OSL_FILE_PATH_HELPER_HXX_
#define _OSL_FILE_PATH_HELPER_HXX_

#ifndef _OSL_FILE_PATH_HELPER_H_
#include "file_path_helper.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace osl
{

 /*******************************************
    systemPathRemoveSeparator
    Removes the last separator from the
    given system path if any and if the path
    is not the root path '/'

    @param  ppustrPath [inout] a system path
            if the path is not the root path
            and the last character is a
            path separator it will be cut off
               ppustrPath must not be NULL and
            must point to a valid rtl_uString

    @returns nothing

  ******************************************/

 inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
 {
     osl_systemPathRemoveSeparator(Path.pData);
 }

 /*******************************************
    systemPathEnsureSeparator
    Adds a trailing path separator to the
    given system path if not already there
    and if the path is not the root path '/'

      @param    pustrPath [inout] a system path
            if the path is not the root path
            '/' and has no trailing separator
            a separator will be added
            ppustrPath must not be NULL and
            must point to a valid rtl_uString

    @returns nothing

  ******************************************/

 inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
 {
     osl_systemPathEnsureSeparator(&Path.pData);
 }

 /*******************************************
    systemPathIsRelativePath
    Returns true if the given path is a
    relative path and so starts not with '/'

    @param  pustrPath [in] a system path
            pustrPath must not be NULL

    @returns sal_True if the given path
             doesn't start with a separator
             else sal_False will be returned

  ******************************************/

 inline bool systemPathIsRelativePath(const rtl::OUString& Path)
 {
    return osl_systemPathIsRelativePath(Path.pData);
 }

 /******************************************
    systemPathIsAbsolutePath
    Returns true if the given path is an
    absolute path and so starts with a '/'

    @param pustrPath [in] a system path
           pustrPath must not be NULL

    @returns sal_True if the given path
             start's with a separator else
             sal_False will be returned

  *****************************************/

 inline bool systemPathIsAbsolutePath(const rtl::OUString& Path)
 {
     return osl_systemPathIsAbsolutePath(Path.pData);
 }

 /******************************************
    systemPathMakeAbsolutePath
    Append a relative path to a base path

    @param  pustrBasePath [in] a system
            path that will be considered as
            base path
            pustrBasePath must not be NULL

    @param  pustrRelPath [in] a system path
            that will be considered as
            relative path
            pustrBasePath must not be NULL

    @param  ppustrAbsolutePath [out] the
            resulting path which is a
            concatination of the base and
            the relative path
            if base path is empty the
            resulting absolute path is the
            relative path
            if relative path is empty the
            resulting absolute path is the
            base path
            if base and relative path are
            empty the resulting absolute
            path is also empty
            ppustrAbsolutePath must not be
            NULL and *ppustrAbsolutePath
            must be 0 or point to a valid
            rtl_uString

  *****************************************/

 inline void systemPathMakeAbsolutePath(
     const rtl::OUString& BasePath,
    const rtl::OUString& RelPath,
    rtl::OUString&       AbsolutePath)
 {
    osl_systemPathMakeAbsolutePath(
        BasePath.pData, RelPath.pData, &AbsolutePath.pData);
 }

 /*****************************************
    systemPathGetParent
    Replaces the last occurrance of a path
    separator with '\0' and returns the
    position where the '/' was replaced

    @param  pustrPath [inout] a system
            path, the last separator of
            this path will be replaced by
            a '\0'
            if the path is the root path
            '/' or the path is considered
            as to have no parent, e.g.
            '/NoParent' or 'NoParent' or
            the path is empty no
            replacement will be made
            pustrPath must not be NULL

    @returns the position of the last path
             separator that was replaced
             or 0 if no replacement took
             place

  ****************************************/

 inline sal_Int32 systemPathGetParent(/*inout*/ rtl::OUString& Path)
 {
    return osl_systemPathGetParent(Path.pData);
 }

 /*****************************************
     systemPathGetFileOrLastDirectoryPart
    Returns the file or the directory part
    of the given path

    @param pustrPath [in] a system path,
           must not be NULL

    @param ppustrFileOrDirPart [out] on
           return receives the last part
           of the given directory or the
           file name
           if pustrPath is the root path
           '/' an empty string will be
           returned
           if pustrPath has a trailing
           '/' the last part before the
           '/' will be returned else
           the part after the last '/'
           will be returned

    @returns nothing

  ****************************************/

 inline void systemPathGetFileNameOrLastDirectoryPart(
     const rtl::OUString& Path,
    rtl::OUString&       FileNameOrLastDirPart)
 {
    osl_systemPathGetFileNameOrLastDirectoryPart(
        Path.pData, &FileNameOrLastDirPart.pData);
 }

 /********************************************
     systemPathIsHiddenFileOrDirectoryEntry
    Returns sal_True if the last part of
    given system path is not '.' or '..'
    alone and starts with a '.'

    @param pustrPath [in] a system path,
           must not be NULL

    @returns sal_True if the last part of
             the given system path starts
             with '.' or sal_False the last
             part is '.' or '..' alone or
             doesn't start with a dot

 *********************************************/

 inline bool systemPathIsHiddenFileOrDirectoryEntry(
     const rtl::OUString& Path)
 {
    return osl_systemPathIsHiddenFileOrDirectoryEntry(Path.pData);
 }

 /************************************************
     systemPathIsLocalOrParentDirectoryEntry
    Returns sal_True if the last part of the given
    system path is the local directory entry '.'
    or the parent directory entry '..'

    @param pustrPath [in] a system path,
           must not be NULL

    @returns sal_True if the last part of the
             given system path is '.' or '..'
             else sal_False

 ************************************************/

 inline bool systemPathIsLocalOrParentDirectoryEntry(
     const rtl::OUString& Path)
 {
    return osl_systemPathIsLocalOrParentDirectoryEntry(Path.pData);
 }

 /************************************************
  searchPath
  ***********************************************/

 inline bool searchPath(
     const rtl::OUString& ustrFilePath,
    const rtl::OUString& ustrSearchPathList,
    rtl::OUString& ustrPathFound)
 {
     return osl_searchPath(
        ustrFilePath.pData,
        ustrSearchPathList.pData,
        &ustrPathFound.pData);
 }

 } // namespace osl

 #endif /* #ifndef _OSL_PATH_HELPER_HXX_ */

<commit_msg>INTEGRATION: CWS warnings01 (1.3.346); FILE MERGED 2005/09/23 00:51:55 sb 1.3.346.2: RESYNC: (1.3-1.4); FILE MERGED 2005/08/30 17:03:15 sb 1.3.346.1: #i53898# Made code warning-free.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: file_path_helper.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 04:17:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _OSL_FILE_PATH_HELPER_HXX_
#define _OSL_FILE_PATH_HELPER_HXX_

#ifndef _OSL_FILE_PATH_HELPER_H_
#include "file_path_helper.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace osl
{

 /*******************************************
    systemPathRemoveSeparator
    Removes the last separator from the
    given system path if any and if the path
    is not the root path '/'

    @param  ppustrPath [inout] a system path
            if the path is not the root path
            and the last character is a
            path separator it will be cut off
               ppustrPath must not be NULL and
            must point to a valid rtl_uString

    @returns nothing

  ******************************************/

 inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
 {
     osl_systemPathRemoveSeparator(Path.pData);
 }

 /*******************************************
    systemPathEnsureSeparator
    Adds a trailing path separator to the
    given system path if not already there
    and if the path is not the root path '/'

      @param    pustrPath [inout] a system path
            if the path is not the root path
            '/' and has no trailing separator
            a separator will be added
            ppustrPath must not be NULL and
            must point to a valid rtl_uString

    @returns nothing

  ******************************************/

 inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
 {
     osl_systemPathEnsureSeparator(&Path.pData);
 }

 /*******************************************
    systemPathIsRelativePath
    Returns true if the given path is a
    relative path and so starts not with '/'

    @param  pustrPath [in] a system path
            pustrPath must not be NULL

    @returns sal_True if the given path
             doesn't start with a separator
             else sal_False will be returned

  ******************************************/

 inline bool systemPathIsRelativePath(const rtl::OUString& Path)
 {
    return osl_systemPathIsRelativePath(Path.pData);
 }

 /******************************************
    systemPathIsAbsolutePath
    Returns true if the given path is an
    absolute path and so starts with a '/'

    @param pustrPath [in] a system path
           pustrPath must not be NULL

    @returns sal_True if the given path
             start's with a separator else
             sal_False will be returned

  *****************************************/

 inline bool systemPathIsAbsolutePath(const rtl::OUString& Path)
 {
     return osl_systemPathIsAbsolutePath(Path.pData);
 }

 /******************************************
    systemPathMakeAbsolutePath
    Append a relative path to a base path

    @param  pustrBasePath [in] a system
            path that will be considered as
            base path
            pustrBasePath must not be NULL

    @param  pustrRelPath [in] a system path
            that will be considered as
            relative path
            pustrBasePath must not be NULL

    @param  ppustrAbsolutePath [out] the
            resulting path which is a
            concatination of the base and
            the relative path
            if base path is empty the
            resulting absolute path is the
            relative path
            if relative path is empty the
            resulting absolute path is the
            base path
            if base and relative path are
            empty the resulting absolute
            path is also empty
            ppustrAbsolutePath must not be
            NULL and *ppustrAbsolutePath
            must be 0 or point to a valid
            rtl_uString

  *****************************************/

 inline void systemPathMakeAbsolutePath(
     const rtl::OUString& BasePath,
    const rtl::OUString& RelPath,
    rtl::OUString&       AbsolutePath)
 {
    osl_systemPathMakeAbsolutePath(
        BasePath.pData, RelPath.pData, &AbsolutePath.pData);
 }

 /*****************************************
     systemPathGetFileOrLastDirectoryPart
    Returns the file or the directory part
    of the given path

    @param pustrPath [in] a system path,
           must not be NULL

    @param ppustrFileOrDirPart [out] on
           return receives the last part
           of the given directory or the
           file name
           if pustrPath is the root path
           '/' an empty string will be
           returned
           if pustrPath has a trailing
           '/' the last part before the
           '/' will be returned else
           the part after the last '/'
           will be returned

    @returns nothing

  ****************************************/

 inline void systemPathGetFileNameOrLastDirectoryPart(
     const rtl::OUString& Path,
    rtl::OUString&       FileNameOrLastDirPart)
 {
    osl_systemPathGetFileNameOrLastDirectoryPart(
        Path.pData, &FileNameOrLastDirPart.pData);
 }

 /********************************************
     systemPathIsHiddenFileOrDirectoryEntry
    Returns sal_True if the last part of
    given system path is not '.' or '..'
    alone and starts with a '.'

    @param pustrPath [in] a system path,
           must not be NULL

    @returns sal_True if the last part of
             the given system path starts
             with '.' or sal_False the last
             part is '.' or '..' alone or
             doesn't start with a dot

 *********************************************/

 inline bool systemPathIsHiddenFileOrDirectoryEntry(
     const rtl::OUString& Path)
 {
    return osl_systemPathIsHiddenFileOrDirectoryEntry(Path.pData);
 }

 /************************************************
     systemPathIsLocalOrParentDirectoryEntry
    Returns sal_True if the last part of the given
    system path is the local directory entry '.'
    or the parent directory entry '..'

    @param pustrPath [in] a system path,
           must not be NULL

    @returns sal_True if the last part of the
             given system path is '.' or '..'
             else sal_False

 ************************************************/

 inline bool systemPathIsLocalOrParentDirectoryEntry(
     const rtl::OUString& Path)
 {
    return osl_systemPathIsLocalOrParentDirectoryEntry(Path.pData);
 }

 /************************************************
  searchPath
  ***********************************************/

 inline bool searchPath(
     const rtl::OUString& ustrFilePath,
    const rtl::OUString& ustrSearchPathList,
    rtl::OUString& ustrPathFound)
 {
     return osl_searchPath(
        ustrFilePath.pData,
        ustrSearchPathList.pData,
        &ustrPathFound.pData);
 }

 } // namespace osl

 #endif /* #ifndef _OSL_PATH_HELPER_HXX_ */

<|endoftext|>