<commit_before>#include <Display.h>
#include <Surface.h>
#include <math.h>

#include "TextField.h"

#ifdef ANDROID
#include <android/log.h>
#endif

namespace nme
{

// --- Stage ---------------------------------------------------------------

// Helper class....
class AutoStageRender
{
   Surface *mSurface;
   Stage   *mToFlip;
   RenderTarget mTarget;
public:
   AutoStageRender(Stage *inStage,int inRGB)
   {
      mSurface = inStage->GetPrimarySurface();
      mToFlip = inStage;
      mTarget = mSurface->BeginRender( Rect(mSurface->Width(),mSurface->Height()),false );

      mSurface->Clear( (inRGB | 0xff000000) & inStage->getBackgroundMask() );
   }
   int Width() const { return mSurface->Width(); }
   int Height() const { return mSurface->Height(); }
   ~AutoStageRender()
   {
      mSurface->EndRender();
      mToFlip->Flip();
   }
   const RenderTarget &Target() { return mTarget; }
};

Stage *Stage::gCurrentStage = 0;

Stage::Stage(bool inInitRef) : DisplayObjectContainer(inInitRef)
{
   gCurrentStage = this;
   mHandler = 0;
   mHandlerData = 0;
   opaqueBackground = 0xffffffff;
   mFocusObject = 0;
   mMouseDownObject = 0;
   mSimpleButton = 0;
   focusRect = true;
   mLastMousePos = UserPoint(0,0);
   scaleMode = ssmShowAll;
   mNominalWidth = 100;
   mNominalHeight = 100;
   mNextWake = 0.0;
   displayState = sdsNormal;
   align = saTopLeft;

   #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
   quality = sqLow;
   #else
   quality = sqBest;
   #endif
}

Stage::~Stage()
{
   if (gCurrentStage==this)
      gCurrentStage = 0;
   if (mFocusObject)
      mFocusObject->DecRef();
   if (mMouseDownObject)
      mMouseDownObject->DecRef();
}

void Stage::SetNextWakeDelay(double inNextWake)
{
   mNextWake = inNextWake + GetTimeStamp();
}

void Stage::SetFocusObject(DisplayObject *inObj,FocusSource inSource,int inKey)
{
   if (inObj==mFocusObject)
      return;

   if (mHandler)
   {
      Event focus(etFocus);
      focus.id = inObj ? inObj->id : 0;
      focus.value = inSource;
      focus.code = inKey;

      mHandler(focus,mHandlerData);

      if (inSource!=fsProgram && focus.result==erCancel)
         return;
   }

   if (!inObj || inObj->getStage()!=this)
   {
      if (mFocusObject)
      {
         mFocusObject->Unfocus();
         mFocusObject->DecRef();
      }
      mFocusObject = 0;
   }
   else
   {
      inObj->IncRef();
      if (mFocusObject)
      {
         mFocusObject->Unfocus();
         mFocusObject->DecRef();
      }
      mFocusObject = inObj;
      inObj->Focus();
   }

}

void Stage::SetNominalSize(int inWidth, int inHeight)
{
   mNominalWidth = inWidth;
   mNominalHeight = inHeight;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::SetEventHandler(EventHandler inHander,void *inUserData)
{
   mHandler = inHander;
   mHandlerData = inUserData;
}

void Stage::HandleEvent(Event &inEvent)
{
   gCurrentStage = this;
   DisplayObject *hit_obj = 0;

   bool primary = inEvent.flags & efPrimaryTouch;

   if ( (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
         inEvent.type==etTouchBegin || inEvent.type==etTouchMove  )
            && primary )
      mLastMousePos = UserPoint(inEvent.x, inEvent.y);

   if (mMouseDownObject && primary)
   {
      switch(inEvent.type)
      {
         case etTouchMove:
         case etMouseMove:
            if (inEvent.flags & efLeftDown)
            {
               mMouseDownObject->Drag(inEvent);
               break;
            }
            // fallthrough
         case etMouseClick:
         case etMouseDown:
         case etMouseUp:
         case etTouchBegin:
         case etTouchTap:
         case etTouchEnd:
            mMouseDownObject->EndDrag(inEvent);
            mMouseDownObject->DecRef();
            mMouseDownObject = 0;
            break;
         default: break;
      }
   }

   if (inEvent.type==etKeyDown || inEvent.type==etKeyUp)
   {
      inEvent.id = mFocusObject ? mFocusObject->id : id;
      if (mHandler)
         mHandler(inEvent,mHandlerData);
      if (inEvent.result==0 && mFocusObject)
         mFocusObject->OnKey(inEvent);
      #ifdef ANDROID
      // Non-cancelled back key ...
      if (inEvent.result==0 && inEvent.value==27 && inEvent.type == etKeyUp)
      {
          StopAnimation();
      }
      #endif
      return;
   }

   if (inEvent.type==etResize)
   {
      CalcStageScaling( inEvent.x, inEvent.y);
   }

   if (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
         inEvent.type==etMouseUp || inEvent.type==etMouseClick ||
         inEvent.type==etTouchBegin || inEvent.type==etTouchEnd ||
         inEvent.type==etTouchMove || inEvent.type==etTouchTap
       )
   {
      UserPoint pixels(inEvent.x,inEvent.y);
      hit_obj = HitTest(pixels);
      //if (inEvent.type!=etTouchMove)
        //ELOG("  type=%d %d,%d obj=%p (%S)", inEvent.type, inEvent.x, inEvent.y, hit_obj, hit_obj?hit_obj->name.c_str():L"(none)");

      SimpleButton *but = hit_obj ? dynamic_cast<SimpleButton *>(hit_obj) : 0;
      inEvent.id = hit_obj ? hit_obj->id : id;
      Cursor cur = hit_obj ? hit_obj->GetCursor() : curPointer;

      if (mSimpleButton && (inEvent.flags & efLeftDown) )
      {
         // Don't change simple button if dragging ...
      }
      else if (but!=mSimpleButton)
      {
         if (but)
            but->IncRef();
         if (mSimpleButton)
         {
            SimpleButton *s = mSimpleButton;
            mSimpleButton = 0;
            s->setMouseState(SimpleButton::stateUp);
            s->DecRef();
         }
         mSimpleButton = but;
      }

      if (mSimpleButton)
      {
         bool over = but==mSimpleButton;
         bool down =  (inEvent.flags & efLeftDown);
         mSimpleButton->setMouseState( over ? ( down ?
             SimpleButton::stateDown : SimpleButton::stateOver) : SimpleButton::stateUp );
         if (!down && !over)
         {
            SimpleButton *s = mSimpleButton;
            mSimpleButton = 0;
            s->DecRef();
         }
         else if (mSimpleButton->getUseHandCursor())
            cur = curHand;
      }

      SetCursor( (gMouseShowCursor || cur>=curTextSelect0) ? cur : curNone );

      UserPoint stage = mStageScale.ApplyInverse(pixels);
      inEvent.x = stage.x;
      inEvent.y = stage.y;
   }

   if (hit_obj)
      hit_obj->IncRef();

   if (mHandler)
      mHandler(inEvent,mHandlerData);

   if (hit_obj)
   {
      if ( (inEvent.type==etMouseDown ||
            (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
           && inEvent.result!=erCancel )
      {
         if (hit_obj->WantsFocus())
            SetFocusObject(hit_obj,fsMouse);
         #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
         else
         {
            EnablePopupKeyboard(false);
            SetFocusObject(0,fsMouse);
         }
         #endif
      }

      if (inEvent.type==etMouseDown || (inEvent.type==etTouchBegin && primary) )
      {
         if (hit_obj->CaptureDown(inEvent))
         {
            hit_obj->IncRef();
            mMouseDownObject = hit_obj;
         }
      }
      if (inEvent.type==etMouseUp && (inEvent.value==3 || inEvent.value==4) )
      {
         TextField *text =  dynamic_cast<TextField *>(hit_obj);
         if (text && text->mouseWheelEnabled)
            text->OnScrollWheel(inEvent.value==3 ? -1 : 1);
      }
   }
   #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
   else if (inEvent.type==etMouseClick ||  inEvent.type==etMouseDown ||
         (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
   {
      EnablePopupKeyboard(false);
      SetFocusObject(0);
   }
   #endif

   if (hit_obj)
      hit_obj->DecRef();
}

void Stage::setOpaqueBackground(uint32 inBG)
{
   opaqueBackground = inBG | 0xff000000;
   DirtyCache();
}

void Stage::RemovingFromStage(DisplayObject *inObject)
{
   DisplayObject *b = mSimpleButton;
   while(b)
   {
      if (b==inObject)
      {
         mSimpleButton->DecRef();
         mSimpleButton = 0;
         break;
      }
      b = b->getParent();
   }

   DisplayObject *f = mFocusObject;
   while(f)
   {
      if (f==inObject)
      {
         mFocusObject->DecRef();
         mFocusObject = 0;
         break;
      }
      f = f->getParent();
   }

   DisplayObject *m = mMouseDownObject;
   while(m)
   {
      if (m==inObject)
      {
         mMouseDownObject->DecRef();
         mMouseDownObject = 0;
         break;
      }
      m = m->getParent();
   }

}

void Stage::CalcStageScaling(double inNewWidth,double inNewHeight)
{
   double StageScaleX=1;
   double StageScaleY=1;
   double StageOX=0;
   double StageOY=0;
   if (inNewWidth<=0 || inNewHeight<=0)
      return;

   if (scaleMode!=ssmNoScale)
   {
      StageScaleX = inNewWidth/(double)mNominalWidth;
      StageScaleY = inNewHeight/(double)mNominalHeight;

      if (scaleMode==ssmNoBorder)
      {
         if (StageScaleX>StageScaleY)
            StageScaleY = StageScaleX;
         else
            StageScaleX = StageScaleY;
      }
      else if (scaleMode==ssmShowAll)
      {
         if (StageScaleX<StageScaleY)
            StageScaleY = StageScaleX;
         else
            StageScaleX = StageScaleY;
      }

   }

   double extra_x = inNewWidth-StageScaleX*mNominalWidth;
   double extra_y = inNewHeight-StageScaleY*mNominalHeight;

   switch(align)
   {
      case saTopLeft: break;
      case saLeft: break;
      case saBottomLeft: break;
      case saTopRight:
      case saRight:
      case saBottomRight:
         StageOX = -extra_y;
         break;
      case saTop:
      case saBottom:
         StageOX = -extra_x/2;
         break;
   }

   switch(align)
   {
      case saTopLeft: break;
      case saTopRight: break;
      case saTop: break;
      case saBottomRight:
      case saBottomLeft:
      case saBottom:
         StageOY = -extra_y;
         break;
      case saLeft:
      case saRight:
         StageOY = -extra_y/2;
         break;
   }
   DirtyCache();

   mStageScale.m00 = StageScaleX;
   mStageScale.m11 = StageScaleY;
   mStageScale.mtx = StageOX;
   mStageScale.mty = StageOY;
}

bool Stage::FinishEditOnEnter()
{
   if (mFocusObject && mFocusObject!=this)
      return mFocusObject->FinishEditOnEnter();
   return false;
}

int Stage::GetAA()
{
   switch(quality)
   {
      case sqLow: return 1;
      case sqMedium: return 2;
      case sqHigh:
      case sqBest:
         return 4;
   }
   return 1;
}

void Stage::BeginRenderStage(bool inClear)
{
   Surface *surface = GetPrimarySurface();
   currentTarget = surface->BeginRender( Rect(surface->Width(),surface->Height()),false );
   if (inClear)
      surface->Clear( (opaqueBackground | 0xff000000) & getBackgroundMask() );
}

void Stage::RenderStage()
{
   ColorTransform::TidyCache();

   if (currentTarget.IsHardware())
      currentTarget.mHardware->SetQuality(quality);

   RenderState state(0, GetAA() );

   state.mTransform.mMatrix = &mStageScale;

   state.mClipRect = Rect( currentTarget.Width(), currentTarget.Height() );

   state.mPhase = rpBitmap;
   state.mRoundSizeToPOW2 = currentTarget.IsHardware();
   Render(currentTarget,state);

   state.mPhase = rpRender;
   Render(currentTarget,state);
}

void Stage::EndRenderStage()
{
   currentTarget = RenderTarget();
   GetPrimarySurface()->EndRender();
   ClearCacheDirty();
   Flip();
}

bool Stage::BuildCache()
{
   Surface *surface = GetPrimarySurface();
   RenderState state(surface, GetAA() );
   state.mTransform.mMatrix = &mStageScale;
   bool wasDirty = false;
   state.mWasDirtyPtr = &wasDirty;

   state.mPhase = rpBitmap;

   RenderTarget target(state.mClipRect, surface->GetHardwareRenderer());
   state.mRoundSizeToPOW2 = surface->GetHardwareRenderer();
   Render(target,state);

   return wasDirty;
}

double Stage::getStageWidth()
{
   Surface *s = GetPrimarySurface();
   if (!s) return 0;
   return s->Width();
}

double Stage::getStageHeight()
{
   Surface *s = GetPrimarySurface();
   if (!s) return 0;
   return s->Height();
}

void Stage::setScaleMode(int inMode)
{
   scaleMode = (StageScaleMode)inMode;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::setAlign(int inAlign)
{
   align = (StageAlign)inAlign;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::setQuality(int inQuality)
{
   quality = (StageQuality)inQuality;
   DirtyCache();
}

void Stage::setDisplayState(int inDisplayState)
{
   displayState = (StageDisplayState)inDisplayState;
   SetFullscreen(inDisplayState>0);
}

Matrix Stage::GetFullMatrix(bool inStageScaling)
{
   if (!inStageScaling)
      return DisplayObject::GetFullMatrix(false);

   return mStageScale.Mult(GetLocalMatrix());
}

DisplayObject *Stage::HitTest(UserPoint inStage,DisplayObject *inRoot,bool inRecurse)
{
   Surface *surface = GetPrimarySurface();

   RenderTarget target = surface->BeginRender( Rect(surface->Width(),surface->Height()),true );

   RenderState state(0, GetAA() );
   state.mClipRect = Rect( inStage.x, inStage.y, 1, 1 );
   Matrix m = mStageScale;
   if (inRoot)
      m = inRoot->GetFullMatrix(true);
   state.mTransform.mMatrix = &m;

   state.mRoundSizeToPOW2 = target.IsHardware();
   state.mPhase = rpHitTest;
   state.mRecurse = inRecurse;

   (inRoot ? inRoot : this) -> Render(target,state);

   surface->EndRender();

   // ELOG("Stage hit %f,%f -> %p\n", inStage.x, inStage.y, state.mHitResult );

   return state.mHitResult;
}

} // end namespace nme

<commit_msg>Update Stage.cpp<commit_after>#include <Display.h>
#include <Surface.h>
#include <math.h>

#include "TextField.h"

#ifdef ANDROID
#include <android/log.h>
#endif

namespace nme
{

// --- Stage ---------------------------------------------------------------

// Helper class....
class AutoStageRender
{
   Surface *mSurface;
   Stage   *mToFlip;
   RenderTarget mTarget;
public:
   AutoStageRender(Stage *inStage,int inRGB)
   {
      mSurface = inStage->GetPrimarySurface();
      mToFlip = inStage;
      mTarget = mSurface->BeginRender( Rect(mSurface->Width(),mSurface->Height()),false );

      mSurface->Clear( (inRGB | 0xff000000) & inStage->getBackgroundMask() );
   }
   int Width() const { return mSurface->Width(); }
   int Height() const { return mSurface->Height(); }
   ~AutoStageRender()
   {
      mSurface->EndRender();
      mToFlip->Flip();
   }
   const RenderTarget &Target() { return mTarget; }
};

Stage *Stage::gCurrentStage = 0;

Stage::Stage(bool inInitRef) : DisplayObjectContainer(inInitRef)
{
   gCurrentStage = this;
   mHandler = 0;
   mHandlerData = 0;
   opaqueBackground = 0xffffffff;
   mFocusObject = 0;
   mMouseDownObject = 0;
   mSimpleButton = 0;
   focusRect = true;
   mLastMousePos = UserPoint(0,0);
   scaleMode = ssmShowAll;
   mNominalWidth = 100;
   mNominalHeight = 100;
   mNextWake = 0.0;
   displayState = sdsNormal;
   align = saTopLeft;

   #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
   quality = sqLow;
   #else
   quality = sqBest;
   #endif
}

Stage::~Stage()
{
   if (gCurrentStage==this)
      gCurrentStage = 0;
   if (mFocusObject)
      mFocusObject->DecRef();
   if (mMouseDownObject)
      mMouseDownObject->DecRef();
}

void Stage::SetNextWakeDelay(double inNextWake)
{
   mNextWake = inNextWake + GetTimeStamp();
}

void Stage::SetFocusObject(DisplayObject *inObj,FocusSource inSource,int inKey)
{
   if (inObj==mFocusObject)
      return;

   if (mHandler)
   {
      Event focus(etFocus);
      focus.id = inObj ? inObj->id : 0;
      focus.value = inSource;
      focus.code = inKey;

      mHandler(focus,mHandlerData);

      if (inSource!=fsProgram && focus.result==erCancel)
         return;
   }

   if (!inObj || inObj->getStage()!=this)
   {
      if (mFocusObject)
      {
         mFocusObject->Unfocus();
         mFocusObject->DecRef();
      }
      mFocusObject = 0;
   }
   else
   {
      inObj->IncRef();
      if (mFocusObject)
      {
         mFocusObject->Unfocus();
         mFocusObject->DecRef();
      }
      mFocusObject = inObj;
      inObj->Focus();
   }

}

void Stage::SetNominalSize(int inWidth, int inHeight)
{
   mNominalWidth = inWidth;
   mNominalHeight = inHeight;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::SetEventHandler(EventHandler inHander,void *inUserData)
{
   mHandler = inHander;
   mHandlerData = inUserData;
}

void Stage::HandleEvent(Event &inEvent)
{
   gCurrentStage = this;
   DisplayObject *hit_obj = 0;

   bool primary = inEvent.flags & efPrimaryTouch;

   if ( (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
         inEvent.type==etTouchBegin || inEvent.type==etTouchMove  )
            && primary )
      mLastMousePos = UserPoint(inEvent.x, inEvent.y);

   if (mMouseDownObject && primary)
   {
      switch(inEvent.type)
      {
         case etTouchMove:
         case etMouseMove:
            if (inEvent.flags & efLeftDown)
            {
               mMouseDownObject->Drag(inEvent);
               break;
            }
            // fallthrough
         case etMouseClick:
         case etMouseDown:
         case etMouseUp:
         case etTouchBegin:
         case etTouchTap:
         case etTouchEnd:
            mMouseDownObject->EndDrag(inEvent);
            mMouseDownObject->DecRef();
            mMouseDownObject = 0;
            break;
         default: break;
      }
   }

   if (inEvent.type==etKeyDown || inEvent.type==etKeyUp || inEvent.type==etChar)
   {
      inEvent.id = mFocusObject ? mFocusObject->id : id;
      if (mHandler)
         mHandler(inEvent,mHandlerData);
      if (inEvent.result==0 && mFocusObject)
         mFocusObject->OnKey(inEvent);
      #ifdef ANDROID
      // Non-cancelled back key ...
      if (inEvent.result==0 && inEvent.value==27 && inEvent.type == etKeyUp)
      {
          StopAnimation();
      }
      #endif
      return;
   }

   if (inEvent.type==etResize)
   {
      CalcStageScaling( inEvent.x, inEvent.y);
   }

   if (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
         inEvent.type==etMouseUp || inEvent.type==etMouseClick ||
         inEvent.type==etTouchBegin || inEvent.type==etTouchEnd ||
         inEvent.type==etTouchMove || inEvent.type==etTouchTap
       )
   {
      UserPoint pixels(inEvent.x,inEvent.y);
      hit_obj = HitTest(pixels);
      //if (inEvent.type!=etTouchMove)
        //ELOG("  type=%d %d,%d obj=%p (%S)", inEvent.type, inEvent.x, inEvent.y, hit_obj, hit_obj?hit_obj->name.c_str():L"(none)");

      SimpleButton *but = hit_obj ? dynamic_cast<SimpleButton *>(hit_obj) : 0;
      inEvent.id = hit_obj ? hit_obj->id : id;
      Cursor cur = hit_obj ? hit_obj->GetCursor() : curPointer;

      if (mSimpleButton && (inEvent.flags & efLeftDown) )
      {
         // Don't change simple button if dragging ...
      }
      else if (but!=mSimpleButton)
      {
         if (but)
            but->IncRef();
         if (mSimpleButton)
         {
            SimpleButton *s = mSimpleButton;
            mSimpleButton = 0;
            s->setMouseState(SimpleButton::stateUp);
            s->DecRef();
         }
         mSimpleButton = but;
      }

      if (mSimpleButton)
      {
         bool over = but==mSimpleButton;
         bool down =  (inEvent.flags & efLeftDown);
         mSimpleButton->setMouseState( over ? ( down ?
             SimpleButton::stateDown : SimpleButton::stateOver) : SimpleButton::stateUp );
         if (!down && !over)
         {
            SimpleButton *s = mSimpleButton;
            mSimpleButton = 0;
            s->DecRef();
         }
         else if (mSimpleButton->getUseHandCursor())
            cur = curHand;
      }

      SetCursor( (gMouseShowCursor || cur>=curTextSelect0) ? cur : curNone );

      UserPoint stage = mStageScale.ApplyInverse(pixels);
      inEvent.x = stage.x;
      inEvent.y = stage.y;
   }

   if (hit_obj)
      hit_obj->IncRef();

   if (mHandler)
      mHandler(inEvent,mHandlerData);

   if (hit_obj)
   {
      if ( (inEvent.type==etMouseDown ||
            (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
           && inEvent.result!=erCancel )
      {
         if (hit_obj->WantsFocus())
            SetFocusObject(hit_obj,fsMouse);
         #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
         else
         {
            EnablePopupKeyboard(false);
            SetFocusObject(0,fsMouse);
         }
         #endif
      }

      if (inEvent.type==etMouseDown || (inEvent.type==etTouchBegin && primary) )
      {
         if (hit_obj->CaptureDown(inEvent))
         {
            hit_obj->IncRef();
            mMouseDownObject = hit_obj;
         }
      }
      if (inEvent.type==etMouseUp && (inEvent.value==3 || inEvent.value==4) )
      {
         TextField *text =  dynamic_cast<TextField *>(hit_obj);
         if (text && text->mouseWheelEnabled)
            text->OnScrollWheel(inEvent.value==3 ? -1 : 1);
      }
   }
   #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
   else if (inEvent.type==etMouseClick ||  inEvent.type==etMouseDown ||
         (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
   {
      EnablePopupKeyboard(false);
      SetFocusObject(0);
   }
   #endif

   if (hit_obj)
      hit_obj->DecRef();
}

void Stage::setOpaqueBackground(uint32 inBG)
{
   opaqueBackground = inBG | 0xff000000;
   DirtyCache();
}

void Stage::RemovingFromStage(DisplayObject *inObject)
{
   DisplayObject *b = mSimpleButton;
   while(b)
   {
      if (b==inObject)
      {
         mSimpleButton->DecRef();
         mSimpleButton = 0;
         break;
      }
      b = b->getParent();
   }

   DisplayObject *f = mFocusObject;
   while(f)
   {
      if (f==inObject)
      {
         mFocusObject->DecRef();
         mFocusObject = 0;
         break;
      }
      f = f->getParent();
   }

   DisplayObject *m = mMouseDownObject;
   while(m)
   {
      if (m==inObject)
      {
         mMouseDownObject->DecRef();
         mMouseDownObject = 0;
         break;
      }
      m = m->getParent();
   }

}

void Stage::CalcStageScaling(double inNewWidth,double inNewHeight)
{
   double StageScaleX=1;
   double StageScaleY=1;
   double StageOX=0;
   double StageOY=0;
   if (inNewWidth<=0 || inNewHeight<=0)
      return;

   if (scaleMode!=ssmNoScale)
   {
      StageScaleX = inNewWidth/(double)mNominalWidth;
      StageScaleY = inNewHeight/(double)mNominalHeight;

      if (scaleMode==ssmNoBorder)
      {
         if (StageScaleX>StageScaleY)
            StageScaleY = StageScaleX;
         else
            StageScaleX = StageScaleY;
      }
      else if (scaleMode==ssmShowAll)
      {
         if (StageScaleX<StageScaleY)
            StageScaleY = StageScaleX;
         else
            StageScaleX = StageScaleY;
      }

   }

   double extra_x = inNewWidth-StageScaleX*mNominalWidth;
   double extra_y = inNewHeight-StageScaleY*mNominalHeight;

   switch(align)
   {
      case saTopLeft: break;
      case saLeft: break;
      case saBottomLeft: break;
      case saTopRight:
      case saRight:
      case saBottomRight:
         StageOX = -extra_y;
         break;
      case saTop:
      case saBottom:
         StageOX = -extra_x/2;
         break;
   }

   switch(align)
   {
      case saTopLeft: break;
      case saTopRight: break;
      case saTop: break;
      case saBottomRight:
      case saBottomLeft:
      case saBottom:
         StageOY = -extra_y;
         break;
      case saLeft:
      case saRight:
         StageOY = -extra_y/2;
         break;
   }
   DirtyCache();

   mStageScale.m00 = StageScaleX;
   mStageScale.m11 = StageScaleY;
   mStageScale.mtx = StageOX;
   mStageScale.mty = StageOY;
}

bool Stage::FinishEditOnEnter()
{
   if (mFocusObject && mFocusObject!=this)
      return mFocusObject->FinishEditOnEnter();
   return false;
}

int Stage::GetAA()
{
   switch(quality)
   {
      case sqLow: return 1;
      case sqMedium: return 2;
      case sqHigh:
      case sqBest:
         return 4;
   }
   return 1;
}

void Stage::BeginRenderStage(bool inClear)
{
   Surface *surface = GetPrimarySurface();
   currentTarget = surface->BeginRender( Rect(surface->Width(),surface->Height()),false );
   if (inClear)
      surface->Clear( (opaqueBackground | 0xff000000) & getBackgroundMask() );
}

void Stage::RenderStage()
{
   ColorTransform::TidyCache();

   if (currentTarget.IsHardware())
      currentTarget.mHardware->SetQuality(quality);

   RenderState state(0, GetAA() );

   state.mTransform.mMatrix = &mStageScale;

   state.mClipRect = Rect( currentTarget.Width(), currentTarget.Height() );

   state.mPhase = rpBitmap;
   state.mRoundSizeToPOW2 = currentTarget.IsHardware();
   Render(currentTarget,state);

   state.mPhase = rpRender;
   Render(currentTarget,state);
}

void Stage::EndRenderStage()
{
   currentTarget = RenderTarget();
   GetPrimarySurface()->EndRender();
   ClearCacheDirty();
   Flip();
}

bool Stage::BuildCache()
{
   Surface *surface = GetPrimarySurface();
   RenderState state(surface, GetAA() );
   state.mTransform.mMatrix = &mStageScale;
   bool wasDirty = false;
   state.mWasDirtyPtr = &wasDirty;

   state.mPhase = rpBitmap;

   RenderTarget target(state.mClipRect, surface->GetHardwareRenderer());
   state.mRoundSizeToPOW2 = surface->GetHardwareRenderer();
   Render(target,state);

   return wasDirty;
}

double Stage::getStageWidth()
{
   Surface *s = GetPrimarySurface();
   if (!s) return 0;
   return s->Width();
}

double Stage::getStageHeight()
{
   Surface *s = GetPrimarySurface();
   if (!s) return 0;
   return s->Height();
}

void Stage::setScaleMode(int inMode)
{
   scaleMode = (StageScaleMode)inMode;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::setAlign(int inAlign)
{
   align = (StageAlign)inAlign;
   CalcStageScaling( getStageWidth(), getStageHeight() );
}

void Stage::setQuality(int inQuality)
{
   quality = (StageQuality)inQuality;
   DirtyCache();
}

void Stage::setDisplayState(int inDisplayState)
{
   displayState = (StageDisplayState)inDisplayState;
   SetFullscreen(inDisplayState>0);
}

Matrix Stage::GetFullMatrix(bool inStageScaling)
{
   if (!inStageScaling)
      return DisplayObject::GetFullMatrix(false);

   return mStageScale.Mult(GetLocalMatrix());
}

DisplayObject *Stage::HitTest(UserPoint inStage,DisplayObject *inRoot,bool inRecurse)
{
   Surface *surface = GetPrimarySurface();

   RenderTarget target = surface->BeginRender( Rect(surface->Width(),surface->Height()),true );

   RenderState state(0, GetAA() );
   state.mClipRect = Rect( inStage.x, inStage.y, 1, 1 );
   Matrix m = mStageScale;
   if (inRoot)
      m = inRoot->GetFullMatrix(true);
   state.mTransform.mMatrix = &m;

   state.mRoundSizeToPOW2 = target.IsHardware();
   state.mPhase = rpHitTest;
   state.mRecurse = inRecurse;

   (inRoot ? inRoot : this) -> Render(target,state);

   surface->EndRender();

   // ELOG("Stage hit %f,%f -> %p\n", inStage.x, inStage.y, state.mHitResult );

   return state.mHitResult;
}

} // end namespace nme

<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "logger.hpp"

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

#include <log4cxx/logger.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/xml/domconfigurator.h>

#include <jubatus/util/lang/cast.h>

#if defined(__FreeBSD__)
#include <sys/thr.h>
#endif

#include <string>

#define LOGGER_NAME "jubatus"

namespace {

inline int gettid() {
#ifdef __APPLE__
  return ::syscall(SYS_thread_selfid);
#elif defined(__FreeBSD__)
  long lwpid;  // NOLINT
  thr_self(&lwpid);
  return static_cast<int>(lwpid);
#else
  return ::syscall(SYS_gettid);
#endif
}

}  // namespace

using jubatus::util::lang::lexical_cast;

namespace jubatus {
namespace server {
namespace common {
namespace logger {

namespace {

inline const char* const_basename(const char* path) {
  const char* base = ::strrchr(path, '/');
  return base ? (base + 1) : path;
}

}  // namespace

stream_logger::stream_logger(
    const log4cxx::LevelPtr& level,
    const char* file,
    int line,
    bool abort)
    : level_(level),
      file_(file),
      line_(line),
      abort_(abort),
      thread_id_(gettid()) {}

stream_logger::~stream_logger() {
  log4cxx::MDC::put("tid", lexical_cast<std::string>(thread_id_));
  log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(LOGGER_NAME);
  if (logger->isEnabledFor(level_)) {
    logger->forcedLog(
        level_,
        buf_.str(),
        log4cxx::spi::LocationInfo(const_basename(file_), "", line_));
  }
  if (abort_) {
    abort();
  }
}

void setup_parameters(const char* progname, const char* host, int port) {
  ::setenv("JUBATUS_PID", lexical_cast<std::string>(::getpid()).c_str(), 1);
  ::setenv("JUBATUS_PROCESS", progname, 1);
  ::setenv("JUBATUS_HOST", host, 1);
  ::setenv("JUBATUS_PORT", lexical_cast<std::string>(port).c_str(), 1);
}

void configure() {
  log4cxx::LayoutPtr layout(
      new log4cxx::PatternLayout("%d %X{tid} %-5p [%F:%L] %m%n"));
  log4cxx::AppenderPtr appender(new log4cxx::ConsoleAppender(layout));
  log4cxx::BasicConfigurator::configure(appender);
}

void configure(const std::string& config_file) {
  // Exception will not be thrown even if there is an error in config file.
  log4cxx::xml::DOMConfigurator::configure(config_file);
}

bool is_configured() {
  log4cxx::LoggerPtr rootLogger = log4cxx::Logger::getRootLogger();
  return rootLogger->getAllAppenders().size() != 0;
}

}  // namespace logger
}  // namespace common
}  // namespace server
}  // namespace jubatus
<commit_msg>set default log level to INFO when config is not specified<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "logger.hpp"

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

#include <log4cxx/logger.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/xml/domconfigurator.h>

#include <jubatus/util/lang/cast.h>

#if defined(__FreeBSD__)
#include <sys/thr.h>
#endif

#include <string>

#define LOGGER_NAME "jubatus"

namespace {

inline int gettid() {
#ifdef __APPLE__
  return ::syscall(SYS_thread_selfid);
#elif defined(__FreeBSD__)
  long lwpid;  // NOLINT
  thr_self(&lwpid);
  return static_cast<int>(lwpid);
#else
  return ::syscall(SYS_gettid);
#endif
}

}  // namespace

using jubatus::util::lang::lexical_cast;

namespace jubatus {
namespace server {
namespace common {
namespace logger {

namespace {

inline const char* const_basename(const char* path) {
  const char* base = ::strrchr(path, '/');
  return base ? (base + 1) : path;
}

}  // namespace

stream_logger::stream_logger(
    const log4cxx::LevelPtr& level,
    const char* file,
    int line,
    bool abort)
    : level_(level),
      file_(file),
      line_(line),
      abort_(abort),
      thread_id_(gettid()) {}

stream_logger::~stream_logger() {
  log4cxx::MDC::put("tid", lexical_cast<std::string>(thread_id_));
  log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(LOGGER_NAME);
  if (logger->isEnabledFor(level_)) {
    logger->forcedLog(
        level_,
        buf_.str(),
        log4cxx::spi::LocationInfo(const_basename(file_), "", line_));
  }
  if (abort_) {
    abort();
  }
}

void setup_parameters(const char* progname, const char* host, int port) {
  ::setenv("JUBATUS_PID", lexical_cast<std::string>(::getpid()).c_str(), 1);
  ::setenv("JUBATUS_PROCESS", progname, 1);
  ::setenv("JUBATUS_HOST", host, 1);
  ::setenv("JUBATUS_PORT", lexical_cast<std::string>(port).c_str(), 1);
}

void configure() {
  log4cxx::LayoutPtr layout(
      new log4cxx::PatternLayout("%d %X{tid} %-5p [%F:%L] %m%n"));
  log4cxx::AppenderPtr appender(new log4cxx::ConsoleAppender(layout));
  log4cxx::BasicConfigurator::configure(appender);
  log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(LOGGER_NAME);
  logger->setLevel(log4cxx::Level::getInfo());
}

void configure(const std::string& config_file) {
  // Exception will not be thrown even if there is an error in config file.
  log4cxx::xml::DOMConfigurator::configure(config_file);
}

bool is_configured() {
  log4cxx::LoggerPtr rootLogger = log4cxx::Logger::getRootLogger();
  return rootLogger->getAllAppenders().size() != 0;
}

}  // namespace logger
}  // namespace common
}  // namespace server
}  // namespace jubatus
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "resource_manager.hh"
#include "manager.hh"
#include "log.hh"
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/map.hpp>
#include "lister.hh"
#include "disk-error-handler.hh"
#include "seastarx.hh"

namespace db {
namespace hints {

static logging::logger resource_manager_logger("hints_resource_manager");

future<dev_t> get_device_id(boost::filesystem::path path) {
    return open_directory(path.native()).then([](file f) {
        return f.stat().then([f = std::move(f)](struct stat st) {
            return st.st_dev;
        });
    });
}

future<bool> is_mountpoint(boost::filesystem::path path) {
    // Special case for '/', which is always a mount point
    if (path == path.parent_path()) {
        return make_ready_future<bool>(true);
    }
    return when_all(get_device_id(path.native()), get_device_id(path.parent_path().native())).then([](std::tuple<future<dev_t>, future<dev_t>> ids) {
        return std::get<0>(ids).get0() != std::get<1>(ids).get0();
    });
}

future<semaphore_units<semaphore_default_exception_factory>> resource_manager::get_send_units_for(size_t buf_size) {
    // Let's approximate the memory size the mutation is going to consume by the size of its serialized form
    size_t hint_memory_budget = std::max(_min_send_hint_budget, buf_size);
    // Allow a very big mutation to be sent out by consuming the whole shard budget
    hint_memory_budget = std::min(hint_memory_budget, _max_send_in_flight_memory);
    resource_manager_logger.trace("memory budget: need {} have {}", hint_memory_budget, _send_limiter.available_units());
    return get_units(_send_limiter, hint_memory_budget);
}

const std::chrono::seconds space_watchdog::_watchdog_period = std::chrono::seconds(1);

space_watchdog::space_watchdog(shard_managers_set& managers, per_device_limits_map& per_device_limits_map)
    : _shard_managers(managers)
    , _per_device_limits_map(per_device_limits_map)
    , _timer([this] { on_timer(); })
{}

void space_watchdog::start() {
    _timer.arm(timer_clock_type::now());
}

future<> space_watchdog::stop() noexcept {
    try {
        return _gate.close().finally([this] { _timer.cancel(); });
    } catch (...) {
        return make_exception_future<>(std::current_exception());
    }
}

future<> space_watchdog::scan_one_ep_dir(boost::filesystem::path path, manager& shard_manager, ep_key_type ep_key) {
    return lister::scan_dir(path, { directory_entry_type::regular }, [this, ep_key, &shard_manager] (lister::path dir, directory_entry de) {
        // Put the current end point ID to state.eps_with_pending_hints when we see the second hints file in its directory
        if (_files_count == 1) {
            shard_manager.add_ep_with_pending_hints(ep_key);
        }
        ++_files_count;

        return io_check(file_size, (dir / de.name.c_str()).c_str()).then([this] (uint64_t fsize) {
            _total_size += fsize;
        });
    });
}

void space_watchdog::on_timer() {
    with_gate(_gate, [this] {
        return futurize_apply([this] {
            _total_size = 0;

            return do_for_each(_shard_managers, [this] (manager& shard_manager) {
                shard_manager.clear_eps_with_pending_hints();

                // The hints directories are organized as follows:
                // <hints root>
                //    |- <shard1 ID>
                //    |  |- <EP1 address>
                //    |     |- <hints file1>
                //    |     |- <hints file2>
                //    |     |- ...
                //    |  |- <EP2 address>
                //    |     |- ...
                //    |  |-...
                //    |- <shard2 ID>
                //    |  |- ...
                //    ...
                //    |- <shardN ID>
                //    |  |- ...
                //
                return lister::scan_dir(shard_manager.hints_dir(), {directory_entry_type::directory}, [this, &shard_manager] (lister::path dir, directory_entry de) {
                    _files_count = 0;
                    // Let's scan per-end-point directories and enumerate hints files...
                    //
                    // Let's check if there is a corresponding end point manager (may not exist if the corresponding DC is
                    // not hintable).
                    // If exists - let's take a file update lock so that files are not changed under our feet. Otherwise, simply
                    // continue to enumeration - there is no one to change them.
                    auto it = shard_manager.find_ep_manager(de.name);
                    if (it != shard_manager.ep_managers_end()) {
                        return with_lock(it->second.file_update_mutex(), [this, &shard_manager, dir = std::move(dir), ep_name = std::move(de.name)]() mutable {
                             return scan_one_ep_dir(dir / ep_name.c_str(), shard_manager, ep_key_type(ep_name));
                        });
                    } else {
                        return scan_one_ep_dir(dir / de.name.c_str(), shard_manager, ep_key_type(de.name));
                    }
                });
            }).then([this] {
                return do_for_each(_per_device_limits_map, [this](per_device_limits_map::value_type& per_device_limits_entry) {
                    space_watchdog::per_device_limits& per_device_limits = per_device_limits_entry.second;

                    size_t adjusted_quota = 0;
                    size_t delta = boost::accumulate(per_device_limits.managers, 0, [] (size_t sum, manager& shard_manager) {
                        return sum + shard_manager.ep_managers_size() * resource_manager::hint_segment_size_in_mb * 1024 * 1024;
                    });
                    if (per_device_limits.max_shard_disk_space_size > delta) {
                        adjusted_quota = per_device_limits.max_shard_disk_space_size - delta;
                    }

                    bool can_hint = _total_size < adjusted_quota;
                    resource_manager_logger.trace("space_watchdog: total_size ({}) {} max_shard_disk_space_size ({})", _total_size, can_hint ? "<" : ">=", adjusted_quota);

                    if (!can_hint) {
                        for (manager& shard_manager : per_device_limits.managers) {
                            shard_manager.forbid_hints_for_eps_with_pending_hints();
                        }
                    } else {
                        for (manager& shard_manager : per_device_limits.managers) {
                            shard_manager.allow_hints();
                        }
    }
                });
            });
        }).handle_exception([this] (auto eptr) {
            resource_manager_logger.trace("space_watchdog: unexpected exception - stop all hints generators");
            // Stop all hint generators if space_watchdog callback failed
            for (manager& shard_manager : _shard_managers) {
                shard_manager.forbid_hints();
            }
        }).finally([this] {
            _timer.arm(_watchdog_period);
        });
    });
}

future<> resource_manager::start(shared_ptr<service::storage_proxy> proxy_ptr, shared_ptr<gms::gossiper> gossiper_ptr, shared_ptr<service::storage_service> ss_ptr) {
    return parallel_for_each(_shard_managers, [proxy_ptr, gossiper_ptr, ss_ptr](manager& m) {
        return m.start(proxy_ptr, gossiper_ptr, ss_ptr);
    }).then([this]() {
        return prepare_per_device_limits();
    }).then([this]() {
        return _space_watchdog.start();
    });
}

future<> resource_manager::stop() noexcept {
    return parallel_for_each(_shard_managers, [](manager& m) {
        return m.stop();
    }).finally([this]() {
        return _space_watchdog.stop();
    });
}

void resource_manager::register_manager(manager& m) {
    _shard_managers.insert(m);
}

future<> resource_manager::prepare_per_device_limits() {
    return do_for_each(_shard_managers, [this] (manager& shard_manager) mutable {
        dev_t device_id = shard_manager.hints_dir_device_id();
        auto it = _per_device_limits_map.find(device_id);
        if (it == _per_device_limits_map.end()) {
            return is_mountpoint(shard_manager.hints_dir().parent_path()).then([this, device_id, &shard_manager](bool is_mountpoint) {
                // By default, give each device 10% of the available disk space. Give each shard an equal share of the available space.
                size_t max_size = boost::filesystem::space(shard_manager.hints_dir().c_str()).capacity / (10 * smp::count);
                // If hints directory is a mountpoint, we assume it's on dedicated (i.e. not shared with data/commitlog/etc) storage.
                // Then, reserve 90% of all space instead of 10% above.
                if (is_mountpoint) {
                    max_size *= 9;
                }
                _per_device_limits_map.emplace(device_id, space_watchdog::per_device_limits{{std::ref(shard_manager)}, max_size});
            });
        } else {
            it->second.managers.emplace_back(std::ref(shard_manager));
            return make_ready_future<>();
        }
    });
}

}
}
<commit_msg>hints: amend a comment in device limits<commit_after>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "resource_manager.hh"
#include "manager.hh"
#include "log.hh"
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/map.hpp>
#include "lister.hh"
#include "disk-error-handler.hh"
#include "seastarx.hh"

namespace db {
namespace hints {

static logging::logger resource_manager_logger("hints_resource_manager");

future<dev_t> get_device_id(boost::filesystem::path path) {
    return open_directory(path.native()).then([](file f) {
        return f.stat().then([f = std::move(f)](struct stat st) {
            return st.st_dev;
        });
    });
}

future<bool> is_mountpoint(boost::filesystem::path path) {
    // Special case for '/', which is always a mount point
    if (path == path.parent_path()) {
        return make_ready_future<bool>(true);
    }
    return when_all(get_device_id(path.native()), get_device_id(path.parent_path().native())).then([](std::tuple<future<dev_t>, future<dev_t>> ids) {
        return std::get<0>(ids).get0() != std::get<1>(ids).get0();
    });
}

future<semaphore_units<semaphore_default_exception_factory>> resource_manager::get_send_units_for(size_t buf_size) {
    // Let's approximate the memory size the mutation is going to consume by the size of its serialized form
    size_t hint_memory_budget = std::max(_min_send_hint_budget, buf_size);
    // Allow a very big mutation to be sent out by consuming the whole shard budget
    hint_memory_budget = std::min(hint_memory_budget, _max_send_in_flight_memory);
    resource_manager_logger.trace("memory budget: need {} have {}", hint_memory_budget, _send_limiter.available_units());
    return get_units(_send_limiter, hint_memory_budget);
}

const std::chrono::seconds space_watchdog::_watchdog_period = std::chrono::seconds(1);

space_watchdog::space_watchdog(shard_managers_set& managers, per_device_limits_map& per_device_limits_map)
    : _shard_managers(managers)
    , _per_device_limits_map(per_device_limits_map)
    , _timer([this] { on_timer(); })
{}

void space_watchdog::start() {
    _timer.arm(timer_clock_type::now());
}

future<> space_watchdog::stop() noexcept {
    try {
        return _gate.close().finally([this] { _timer.cancel(); });
    } catch (...) {
        return make_exception_future<>(std::current_exception());
    }
}

future<> space_watchdog::scan_one_ep_dir(boost::filesystem::path path, manager& shard_manager, ep_key_type ep_key) {
    return lister::scan_dir(path, { directory_entry_type::regular }, [this, ep_key, &shard_manager] (lister::path dir, directory_entry de) {
        // Put the current end point ID to state.eps_with_pending_hints when we see the second hints file in its directory
        if (_files_count == 1) {
            shard_manager.add_ep_with_pending_hints(ep_key);
        }
        ++_files_count;

        return io_check(file_size, (dir / de.name.c_str()).c_str()).then([this] (uint64_t fsize) {
            _total_size += fsize;
        });
    });
}

void space_watchdog::on_timer() {
    with_gate(_gate, [this] {
        return futurize_apply([this] {
            _total_size = 0;

            return do_for_each(_shard_managers, [this] (manager& shard_manager) {
                shard_manager.clear_eps_with_pending_hints();

                // The hints directories are organized as follows:
                // <hints root>
                //    |- <shard1 ID>
                //    |  |- <EP1 address>
                //    |     |- <hints file1>
                //    |     |- <hints file2>
                //    |     |- ...
                //    |  |- <EP2 address>
                //    |     |- ...
                //    |  |-...
                //    |- <shard2 ID>
                //    |  |- ...
                //    ...
                //    |- <shardN ID>
                //    |  |- ...
                //
                return lister::scan_dir(shard_manager.hints_dir(), {directory_entry_type::directory}, [this, &shard_manager] (lister::path dir, directory_entry de) {
                    _files_count = 0;
                    // Let's scan per-end-point directories and enumerate hints files...
                    //
                    // Let's check if there is a corresponding end point manager (may not exist if the corresponding DC is
                    // not hintable).
                    // If exists - let's take a file update lock so that files are not changed under our feet. Otherwise, simply
                    // continue to enumeration - there is no one to change them.
                    auto it = shard_manager.find_ep_manager(de.name);
                    if (it != shard_manager.ep_managers_end()) {
                        return with_lock(it->second.file_update_mutex(), [this, &shard_manager, dir = std::move(dir), ep_name = std::move(de.name)]() mutable {
                             return scan_one_ep_dir(dir / ep_name.c_str(), shard_manager, ep_key_type(ep_name));
                        });
                    } else {
                        return scan_one_ep_dir(dir / de.name.c_str(), shard_manager, ep_key_type(de.name));
                    }
                });
            }).then([this] {
                return do_for_each(_per_device_limits_map, [this](per_device_limits_map::value_type& per_device_limits_entry) {
                    space_watchdog::per_device_limits& per_device_limits = per_device_limits_entry.second;

                    size_t adjusted_quota = 0;
                    size_t delta = boost::accumulate(per_device_limits.managers, 0, [] (size_t sum, manager& shard_manager) {
                        return sum + shard_manager.ep_managers_size() * resource_manager::hint_segment_size_in_mb * 1024 * 1024;
                    });
                    if (per_device_limits.max_shard_disk_space_size > delta) {
                        adjusted_quota = per_device_limits.max_shard_disk_space_size - delta;
                    }

                    bool can_hint = _total_size < adjusted_quota;
                    resource_manager_logger.trace("space_watchdog: total_size ({}) {} max_shard_disk_space_size ({})", _total_size, can_hint ? "<" : ">=", adjusted_quota);

                    if (!can_hint) {
                        for (manager& shard_manager : per_device_limits.managers) {
                            shard_manager.forbid_hints_for_eps_with_pending_hints();
                        }
                    } else {
                        for (manager& shard_manager : per_device_limits.managers) {
                            shard_manager.allow_hints();
                        }
    }
                });
            });
        }).handle_exception([this] (auto eptr) {
            resource_manager_logger.trace("space_watchdog: unexpected exception - stop all hints generators");
            // Stop all hint generators if space_watchdog callback failed
            for (manager& shard_manager : _shard_managers) {
                shard_manager.forbid_hints();
            }
        }).finally([this] {
            _timer.arm(_watchdog_period);
        });
    });
}

future<> resource_manager::start(shared_ptr<service::storage_proxy> proxy_ptr, shared_ptr<gms::gossiper> gossiper_ptr, shared_ptr<service::storage_service> ss_ptr) {
    return parallel_for_each(_shard_managers, [proxy_ptr, gossiper_ptr, ss_ptr](manager& m) {
        return m.start(proxy_ptr, gossiper_ptr, ss_ptr);
    }).then([this]() {
        return prepare_per_device_limits();
    }).then([this]() {
        return _space_watchdog.start();
    });
}

future<> resource_manager::stop() noexcept {
    return parallel_for_each(_shard_managers, [](manager& m) {
        return m.stop();
    }).finally([this]() {
        return _space_watchdog.stop();
    });
}

void resource_manager::register_manager(manager& m) {
    _shard_managers.insert(m);
}

future<> resource_manager::prepare_per_device_limits() {
    return do_for_each(_shard_managers, [this] (manager& shard_manager) mutable {
        dev_t device_id = shard_manager.hints_dir_device_id();
        auto it = _per_device_limits_map.find(device_id);
        if (it == _per_device_limits_map.end()) {
            return is_mountpoint(shard_manager.hints_dir().parent_path()).then([this, device_id, &shard_manager](bool is_mountpoint) {
                // By default, give each group of managers 10% of the available disk space. Give each shard an equal share of the available space.
                size_t max_size = boost::filesystem::space(shard_manager.hints_dir().c_str()).capacity / (10 * smp::count);
                // If hints directory is a mountpoint, we assume it's on dedicated (i.e. not shared with data/commitlog/etc) storage.
                // Then, reserve 90% of all space instead of 10% above.
                if (is_mountpoint) {
                    max_size *= 9;
                }
                _per_device_limits_map.emplace(device_id, space_watchdog::per_device_limits{{std::ref(shard_manager)}, max_size});
            });
        } else {
            it->second.managers.emplace_back(std::ref(shard_manager));
            return make_ready_future<>();
        }
    });
}

}
}
<|endoftext|>


<commit_before>#include "PickUp.h"
#include "../RobotMap.h"

PickUp :: Pickup(int ) :Subsystem ("PickUp") {

}
<commit_msg>Still working on PickUp<commit_after>#include "PickUp.h"
#include "../RobotMap.h"

PickUp :: Pickup(int intakePort) :Subsystem ("PickUp") {

}
<|endoftext|>


<commit_before>// Copyright 2008-2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>

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

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/registry.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/default_plugin/plugin_impl.h"
#include "webkit/glue/plugins/plugin_constants_win.h"
#include "webkit/glue/plugins/plugin_list.h"

const char kTestCompleteCookie[] = "status";
const char kTestCompleteSuccess[] = "OK";
const int kShortWaitTimeout = 10 * 1000;
const int kLongWaitTimeout  = 30 * 1000;

class PluginTest : public UITest {
 protected:
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(kUseOldWMPPluginSwitch);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchWithValue(switches::kTestSandbox,
                                              L"security_tests.dll");
    }

    UITest::SetUp();
  }

  void TestPlugin(const std::wstring& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  GURL GetTestUrl(const std::wstring &test_case, bool mock_http) {
    if (mock_http)
      return URLRequestMockHTTPJob::GetMockUrl(L"plugin/" + test_case);

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.AppendASCII("plugin");
    path = path.Append(FilePath::FromWStringHack(test_case));
    return net::FilePathToFileURL(path);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    const int kSleepTime = 500;      // 2 times per second
    const int kMaxIntervals = wait_time / kSleepTime;

    GURL url = GetTestUrl(L"done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    std::string done_str;
    for (int i = 0; i < kMaxIntervals; ++i) {
      Sleep(kSleepTime);

      // The webpage being tested has javascript which sets a cookie
      // which signals completion of the test.
      std::string cookieName = kTestCompleteCookie;
      tab->GetCookieByName(url, cookieName, &done_str);
      if (!done_str.empty())
        break;
    }

    EXPECT_EQ(kTestCompleteSuccess, done_str);
  }
};

TEST_F(PluginTest, Quicktime) {
  TestPlugin(L"quicktime.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, MediaPlayerNew) {
  TestPlugin(L"wmp_new.html", kShortWaitTimeout, false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin(L"wmp_old.html", kLongWaitTimeout, false);
}

TEST_F(PluginTest, Real) {
  TestPlugin(L"real.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, Flash) {
  TestPlugin(L"flash.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin(L"flash-octet-stream.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, FlashSecurity) {
  TestPlugin(L"flash.html", kShortWaitTimeout, false);
}

// http://crbug.com/16114
TEST_F(PluginTest, FlashLayoutWhilePainting) {
  TestPlugin(L"flash-layout-while-painting.html", kShortWaitTimeout, true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin(L"Java.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, Silverlight) {
  TestPlugin(L"silverlight.html", kShortWaitTimeout, false);
}
<commit_msg>Disable flaky plugin tests. These keep causing bogus automatic tree closures.<commit_after>// Copyright 2008-2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>

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

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/registry.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/default_plugin/plugin_impl.h"
#include "webkit/glue/plugins/plugin_constants_win.h"
#include "webkit/glue/plugins/plugin_list.h"

const char kTestCompleteCookie[] = "status";
const char kTestCompleteSuccess[] = "OK";
const int kShortWaitTimeout = 10 * 1000;
const int kLongWaitTimeout  = 30 * 1000;

class PluginTest : public UITest {
 protected:
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(kUseOldWMPPluginSwitch);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchWithValue(switches::kTestSandbox,
                                              L"security_tests.dll");
    }

    UITest::SetUp();
  }

  void TestPlugin(const std::wstring& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  GURL GetTestUrl(const std::wstring &test_case, bool mock_http) {
    if (mock_http)
      return URLRequestMockHTTPJob::GetMockUrl(L"plugin/" + test_case);

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.AppendASCII("plugin");
    path = path.Append(FilePath::FromWStringHack(test_case));
    return net::FilePathToFileURL(path);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    const int kSleepTime = 500;      // 2 times per second
    const int kMaxIntervals = wait_time / kSleepTime;

    GURL url = GetTestUrl(L"done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    std::string done_str;
    for (int i = 0; i < kMaxIntervals; ++i) {
      Sleep(kSleepTime);

      // The webpage being tested has javascript which sets a cookie
      // which signals completion of the test.
      std::string cookieName = kTestCompleteCookie;
      tab->GetCookieByName(url, cookieName, &done_str);
      if (!done_str.empty())
        break;
    }

    EXPECT_EQ(kTestCompleteSuccess, done_str);
  }
};

TEST_F(PluginTest, Quicktime) {
  TestPlugin(L"quicktime.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, MediaPlayerNew) {
  TestPlugin(L"wmp_new.html", kShortWaitTimeout, false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin(L"wmp_old.html", kLongWaitTimeout, false);
}

TEST_F(PluginTest, Real) {
  TestPlugin(L"real.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, Flash) {
  TestPlugin(L"flash.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin(L"flash-octet-stream.html", kShortWaitTimeout, false);
}

TEST_F(PluginTest, FlashSecurity) {
  TestPlugin(L"flash.html", kShortWaitTimeout, false);
}

// http://crbug.com/16114
// Disabled for http://crbug.com/21538
TEST_F(PluginTest, DISABLED_FlashLayoutWhilePainting) {
  TestPlugin(L"flash-layout-while-painting.html", kShortWaitTimeout, true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin(L"Java.html", kShortWaitTimeout, false);
}

// Disabled for http://crbug.com/22666
TEST_F(PluginTest, DISABLED_Silverlight) {
  TestPlugin(L"silverlight.html", kShortWaitTimeout, false);
}
<|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.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>
#endif

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

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/plugin_download_helper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/capturing_net_log.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/base/net_util.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/plugin_switches.h"

#if defined(OS_WIN)
#include "base/win/registry.h"
#endif

class PluginTest : public UITest {
 public:
  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  static GURL GetTestUrl(const std::string &test_case, bool mock_http) {
    static const FilePath::CharType kPluginPath[] = FILE_PATH_LITERAL("plugin");
    if (mock_http) {
      FilePath plugin_path = FilePath(kPluginPath).AppendASCII(test_case);
      return URLRequestMockHTTPJob::GetMockUrl(plugin_path);
    }

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.Append(kPluginPath).AppendASCII(test_case);
    return net::FilePathToFileURL(path);
  }

 protected:
#if defined(OS_WIN)
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      base::win::RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchASCII(switches::kTestSandbox,
                                          "security_tests.dll");
    }

    UITest::SetUp();
  }
#endif  // defined(OS_WIN)

  void TestPlugin(const std::string& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    static const char kTestCompleteCookie[] = "status";
    static const char kTestCompleteSuccess[] = "OK";

    GURL url = GetTestUrl("done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    const std::string result =
        WaitUntilCookieNonEmpty(tab, url, kTestCompleteCookie, wait_time);
    ASSERT_EQ(kTestCompleteSuccess, result);
  }
};

TEST_F(PluginTest, Flash) {
  // Note: This does not work with the npwrapper on 64-bit Linux. Install the
  // native 64-bit Flash to run the test.
  // TODO(thestig) Update this list if we decide to only test against internal
  // Flash plugin in the future?
  std::string kFlashQuery =
#if defined(OS_WIN)
      "npswf32.dll"
#elif defined(OS_MACOSX)
      "Flash Player.plugin"
#elif defined(OS_POSIX)
      "libflashplayer.so"
#endif
      ;
  TestPlugin("flash.html?" + kFlashQuery, action_max_timeout_ms(), false);
}

class ClickToPlayPluginTest : public PluginTest {
 public:
  ClickToPlayPluginTest() {
    dom_automation_enabled_ = true;
  }
};

TEST_F(ClickToPlayPluginTest, Flash) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  GURL url = GetTestUrl("flash-clicktoplay.html", true);
  NavigateToURL(url);

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

TEST_F(ClickToPlayPluginTest, FlashDocument) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());
  GURL url = GetTestUrl("js-invoker.swf?callback=done", true);
  NavigateToURL(url);

  // Inject the callback function into the HTML page generated by the browser.
  ASSERT_TRUE(tab->ExecuteJavaScript("window.done = function() {"
                                     "  window.location = \"done.html\";"
                                     "}"));

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

#if defined(OS_WIN)
// Windows only test
TEST_F(PluginTest, DISABLED_FlashSecurity) {
  TestPlugin("flash.html", action_max_timeout_ms(), false);
}
#endif  // defined(OS_WIN)

#if defined(OS_WIN)
// TODO(port) Port the following tests to platforms that have the required
// plugins.
// Flaky: http://crbug.com/55915
TEST_F(PluginTest, FLAKY_Quicktime) {
  TestPlugin("quicktime.html", action_max_timeout_ms(), false);
}

// Disabled on Release bots - http://crbug.com/44662
#if defined(NDEBUG)
#define MediaPlayerNew DISABLED_MediaPlayerNew
#endif
TEST_F(PluginTest, MediaPlayerNew) {
  TestPlugin("wmp_new.html", action_max_timeout_ms(), false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin("wmp_old.html", action_max_timeout_ms(), false);
}

#if defined(NDEBUG)
#define Real DISABLED_Real
#endif
// Disabled on Release bots - http://crbug.com/44673
TEST_F(PluginTest, Real) {
  TestPlugin("real.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin("flash-octet-stream.html", action_max_timeout_ms(), false);
}

#if defined(OS_WIN)
// http://crbug.com/53926
TEST_F(PluginTest, FLAKY_FlashLayoutWhilePainting) {
#else
TEST_F(PluginTest, FlashLayoutWhilePainting) {
#endif
  TestPlugin("flash-layout-while-painting.html", action_max_timeout_ms(), true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin("Java.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, Silverlight) {
  TestPlugin("silverlight.html", action_max_timeout_ms(), false);
}

// This class provides functionality to test the plugin installer download
// file functionality.
class PluginInstallerDownloadTest
    : public PluginDownloadUrlHelper::DownloadDelegate,
      public testing::Test {
 public:
  // This class provides HTTP request context information for the downloads.
  class UploadRequestContext : public URLRequestContext {
   public:
    UploadRequestContext() {
      Initialize();
    }

    ~UploadRequestContext() {
      DVLOG(1) << __FUNCTION__;
      delete http_transaction_factory_;
      delete http_auth_handler_factory_;
      delete cert_verifier_;
      delete host_resolver_;
    }

    void Initialize() {
      host_resolver_ =
          net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
                                        NULL, NULL);
      cert_verifier_ = new net::CertVerifier;
      net::ProxyConfigService* proxy_config_service =
          net::ProxyService::CreateSystemProxyConfigService(NULL, NULL);
      DCHECK(proxy_config_service);

      const size_t kNetLogBound = 50u;
      net_log_.reset(new net::CapturingNetLog(kNetLogBound));

      proxy_service_ = net::ProxyService::CreateUsingSystemProxyResolver(
          proxy_config_service, 0, net_log_.get());
      DCHECK(proxy_service_);

      ssl_config_service_ = new net::SSLConfigServiceDefaults;
      http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
          host_resolver_);
      http_transaction_factory_ = new net::HttpCache(
          net::HttpNetworkLayer::CreateFactory(host_resolver_,
                                               cert_verifier_,
                                               NULL /* dnsrr_resolver */,
                                               NULL /* dns_cert_checker */,
                                               NULL /* ssl_host_info_factory */,
                                               proxy_service_,
                                               ssl_config_service_,
                                               http_auth_handler_factory_,
                                               network_delegate_,
                                               NULL),
          net::HttpCache::DefaultBackend::InMemory(0));
    }

   private:
    scoped_ptr<net::NetLog> net_log_;
    scoped_ptr<net::URLSecurityManager> url_security_manager_;
  };

  PluginInstallerDownloadTest()
      : success_(false),
        download_helper_(NULL) {}
  ~PluginInstallerDownloadTest() {}

  void Start() {
    initial_download_path_ = PluginTest::GetTestUrl("flash.html", false);
    download_helper_ = new PluginDownloadUrlHelper(
        initial_download_path_.spec(), base::GetCurrentProcId(), NULL,
        static_cast<PluginDownloadUrlHelper::DownloadDelegate*>(this));
    download_helper_->InitiateDownload(new UploadRequestContext);

    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, new MessageLoop::QuitTask,
        TestTimeouts::action_max_timeout_ms());
  }

  virtual void OnDownloadCompleted(const FilePath& download_path,
                                   bool success) {
    success_ = success;
    final_download_path_ = download_path;
    MessageLoop::current()->Quit();
    download_helper_ = NULL;
  }

  FilePath final_download_path() const {
    return final_download_path_;
  }

  FilePath initial_download_path() const {
    return final_download_path_;
  }

  bool success() const {
    return success_;
  }

 private:
  FilePath final_download_path_;
  PluginDownloadUrlHelper* download_helper_;
  bool success_;
  GURL initial_download_path_;
};

// This test validates that the plugin downloader downloads the specified file
// to a temporary path with the same file name.
TEST_F(PluginInstallerDownloadTest, PluginInstallerDownloadPathTest) {
  MessageLoop loop(MessageLoop::TYPE_IO);
  Start();
  loop.Run();

  EXPECT_TRUE(success());
  EXPECT_TRUE(initial_download_path().BaseName().value() ==
              final_download_path().BaseName().value());
}
#endif  // defined(OS_WIN)
<commit_msg>Disabling the MediaPlayerNew plugin test as it seems to fail consistently causing the XP Perf dbg builder to turn red.<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.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>
#endif

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

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/plugin_download_helper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/capturing_net_log.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/base/net_util.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/plugin_switches.h"

#if defined(OS_WIN)
#include "base/win/registry.h"
#endif

class PluginTest : public UITest {
 public:
  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  static GURL GetTestUrl(const std::string &test_case, bool mock_http) {
    static const FilePath::CharType kPluginPath[] = FILE_PATH_LITERAL("plugin");
    if (mock_http) {
      FilePath plugin_path = FilePath(kPluginPath).AppendASCII(test_case);
      return URLRequestMockHTTPJob::GetMockUrl(plugin_path);
    }

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.Append(kPluginPath).AppendASCII(test_case);
    return net::FilePathToFileURL(path);
  }

 protected:
#if defined(OS_WIN)
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      base::win::RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchASCII(switches::kTestSandbox,
                                          "security_tests.dll");
    }

    UITest::SetUp();
  }
#endif  // defined(OS_WIN)

  void TestPlugin(const std::string& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    static const char kTestCompleteCookie[] = "status";
    static const char kTestCompleteSuccess[] = "OK";

    GURL url = GetTestUrl("done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    const std::string result =
        WaitUntilCookieNonEmpty(tab, url, kTestCompleteCookie, wait_time);
    ASSERT_EQ(kTestCompleteSuccess, result);
  }
};

TEST_F(PluginTest, Flash) {
  // Note: This does not work with the npwrapper on 64-bit Linux. Install the
  // native 64-bit Flash to run the test.
  // TODO(thestig) Update this list if we decide to only test against internal
  // Flash plugin in the future?
  std::string kFlashQuery =
#if defined(OS_WIN)
      "npswf32.dll"
#elif defined(OS_MACOSX)
      "Flash Player.plugin"
#elif defined(OS_POSIX)
      "libflashplayer.so"
#endif
      ;
  TestPlugin("flash.html?" + kFlashQuery, action_max_timeout_ms(), false);
}

class ClickToPlayPluginTest : public PluginTest {
 public:
  ClickToPlayPluginTest() {
    dom_automation_enabled_ = true;
  }
};

TEST_F(ClickToPlayPluginTest, Flash) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  GURL url = GetTestUrl("flash-clicktoplay.html", true);
  NavigateToURL(url);

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

TEST_F(ClickToPlayPluginTest, FlashDocument) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());
  GURL url = GetTestUrl("js-invoker.swf?callback=done", true);
  NavigateToURL(url);

  // Inject the callback function into the HTML page generated by the browser.
  ASSERT_TRUE(tab->ExecuteJavaScript("window.done = function() {"
                                     "  window.location = \"done.html\";"
                                     "}"));

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

#if defined(OS_WIN)
// Windows only test
TEST_F(PluginTest, DISABLED_FlashSecurity) {
  TestPlugin("flash.html", action_max_timeout_ms(), false);
}
#endif  // defined(OS_WIN)

#if defined(OS_WIN)
// TODO(port) Port the following tests to platforms that have the required
// plugins.
// Flaky: http://crbug.com/55915
TEST_F(PluginTest, FLAKY_Quicktime) {
  TestPlugin("quicktime.html", action_max_timeout_ms(), false);
}

// Disabled - http://crbug.com/44662
TEST_F(PluginTest, DISABLED_MediaPlayerNew) {
  TestPlugin("wmp_new.html", action_max_timeout_ms(), false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin("wmp_old.html", action_max_timeout_ms(), false);
}

#if defined(NDEBUG)
#define Real DISABLED_Real
#endif
// Disabled on Release bots - http://crbug.com/44673
TEST_F(PluginTest, Real) {
  TestPlugin("real.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin("flash-octet-stream.html", action_max_timeout_ms(), false);
}

#if defined(OS_WIN)
// http://crbug.com/53926
TEST_F(PluginTest, FLAKY_FlashLayoutWhilePainting) {
#else
TEST_F(PluginTest, FlashLayoutWhilePainting) {
#endif
  TestPlugin("flash-layout-while-painting.html", action_max_timeout_ms(), true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin("Java.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, Silverlight) {
  TestPlugin("silverlight.html", action_max_timeout_ms(), false);
}

// This class provides functionality to test the plugin installer download
// file functionality.
class PluginInstallerDownloadTest
    : public PluginDownloadUrlHelper::DownloadDelegate,
      public testing::Test {
 public:
  // This class provides HTTP request context information for the downloads.
  class UploadRequestContext : public URLRequestContext {
   public:
    UploadRequestContext() {
      Initialize();
    }

    ~UploadRequestContext() {
      DVLOG(1) << __FUNCTION__;
      delete http_transaction_factory_;
      delete http_auth_handler_factory_;
      delete cert_verifier_;
      delete host_resolver_;
    }

    void Initialize() {
      host_resolver_ =
          net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
                                        NULL, NULL);
      cert_verifier_ = new net::CertVerifier;
      net::ProxyConfigService* proxy_config_service =
          net::ProxyService::CreateSystemProxyConfigService(NULL, NULL);
      DCHECK(proxy_config_service);

      const size_t kNetLogBound = 50u;
      net_log_.reset(new net::CapturingNetLog(kNetLogBound));

      proxy_service_ = net::ProxyService::CreateUsingSystemProxyResolver(
          proxy_config_service, 0, net_log_.get());
      DCHECK(proxy_service_);

      ssl_config_service_ = new net::SSLConfigServiceDefaults;
      http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
          host_resolver_);
      http_transaction_factory_ = new net::HttpCache(
          net::HttpNetworkLayer::CreateFactory(host_resolver_,
                                               cert_verifier_,
                                               NULL /* dnsrr_resolver */,
                                               NULL /* dns_cert_checker */,
                                               NULL /* ssl_host_info_factory */,
                                               proxy_service_,
                                               ssl_config_service_,
                                               http_auth_handler_factory_,
                                               network_delegate_,
                                               NULL),
          net::HttpCache::DefaultBackend::InMemory(0));
    }

   private:
    scoped_ptr<net::NetLog> net_log_;
    scoped_ptr<net::URLSecurityManager> url_security_manager_;
  };

  PluginInstallerDownloadTest()
      : success_(false),
        download_helper_(NULL) {}
  ~PluginInstallerDownloadTest() {}

  void Start() {
    initial_download_path_ = PluginTest::GetTestUrl("flash.html", false);
    download_helper_ = new PluginDownloadUrlHelper(
        initial_download_path_.spec(), base::GetCurrentProcId(), NULL,
        static_cast<PluginDownloadUrlHelper::DownloadDelegate*>(this));
    download_helper_->InitiateDownload(new UploadRequestContext);

    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, new MessageLoop::QuitTask,
        TestTimeouts::action_max_timeout_ms());
  }

  virtual void OnDownloadCompleted(const FilePath& download_path,
                                   bool success) {
    success_ = success;
    final_download_path_ = download_path;
    MessageLoop::current()->Quit();
    download_helper_ = NULL;
  }

  FilePath final_download_path() const {
    return final_download_path_;
  }

  FilePath initial_download_path() const {
    return final_download_path_;
  }

  bool success() const {
    return success_;
  }

 private:
  FilePath final_download_path_;
  PluginDownloadUrlHelper* download_helper_;
  bool success_;
  GURL initial_download_path_;
};

// This test validates that the plugin downloader downloads the specified file
// to a temporary path with the same file name.
TEST_F(PluginInstallerDownloadTest, PluginInstallerDownloadPathTest) {
  MessageLoop loop(MessageLoop::TYPE_IO);
  Start();
  loop.Run();

  EXPECT_TRUE(success());
  EXPECT_TRUE(initial_download_path().BaseName().value() ==
              final_download_path().BaseName().value());
}
#endif  // defined(OS_WIN)
<|endoftext|>