layout/xul/nsScrollbarButtonFrame.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 //
     7 // Eric Vaughan
     8 // Netscape Communications
     9 //
    10 // See documentation in associated header file
    11 //
    13 #include "nsScrollbarButtonFrame.h"
    14 #include "nsPresContext.h"
    15 #include "nsIContent.h"
    16 #include "nsCOMPtr.h"
    17 #include "nsNameSpaceManager.h"
    18 #include "nsGkAtoms.h"
    19 #include "nsSliderFrame.h"
    20 #include "nsScrollbarFrame.h"
    21 #include "nsIScrollbarMediator.h"
    22 #include "nsRepeatService.h"
    23 #include "mozilla/LookAndFeel.h"
    24 #include "mozilla/MouseEvents.h"
    26 using namespace mozilla;
    28 //
    29 // NS_NewToolbarFrame
    30 //
    31 // Creates a new Toolbar frame and returns it
    32 //
    33 nsIFrame*
    34 NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
    35 {
    36   return new (aPresShell) nsScrollbarButtonFrame(aPresShell, aContext);
    37 }
    39 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
    41 nsresult
    42 nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
    43                                     WidgetGUIEvent* aEvent,
    44                                     nsEventStatus* aEventStatus)
    45 {  
    46   NS_ENSURE_ARG_POINTER(aEventStatus);
    48   // If a web page calls event.preventDefault() we still want to
    49   // scroll when scroll arrow is clicked. See bug 511075.
    50   if (!mContent->IsInNativeAnonymousSubtree() &&
    51       nsEventStatus_eConsumeNoDefault == *aEventStatus) {
    52     return NS_OK;
    53   }
    55   switch (aEvent->message) {
    56     case NS_MOUSE_BUTTON_DOWN:
    57       mCursorOnThis = true;
    58       // if we didn't handle the press ourselves, pass it on to the superclass
    59       if (HandleButtonPress(aPresContext, aEvent, aEventStatus)) {
    60         return NS_OK;
    61       }
    62       break;
    63     case NS_MOUSE_BUTTON_UP:
    64       HandleRelease(aPresContext, aEvent, aEventStatus);
    65       break;
    66     case NS_MOUSE_EXIT_SYNTH:
    67       mCursorOnThis = false;
    68       break;
    69     case NS_MOUSE_MOVE: {
    70       nsPoint cursor =
    71         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
    72       nsRect frameRect(nsPoint(0, 0), GetSize());
    73       mCursorOnThis = frameRect.Contains(cursor);
    74       break;
    75     }
    76   }
    78   return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
    79 }
    82 bool
    83 nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
    84                                           WidgetGUIEvent* aEvent,
    85                                           nsEventStatus* aEventStatus)
    86 {
    87   // Get the desired action for the scrollbar button.
    88   LookAndFeel::IntID tmpAction;
    89   uint16_t button = aEvent->AsMouseEvent()->button;
    90   if (button == WidgetMouseEvent::eLeftButton) {
    91     tmpAction = LookAndFeel::eIntID_ScrollButtonLeftMouseButtonAction;
    92   } else if (button == WidgetMouseEvent::eMiddleButton) {
    93     tmpAction = LookAndFeel::eIntID_ScrollButtonMiddleMouseButtonAction;
    94   } else if (button == WidgetMouseEvent::eRightButton) {
    95     tmpAction = LookAndFeel::eIntID_ScrollButtonRightMouseButtonAction;
    96   } else {
    97     return false;
    98   }
   100   // Get the button action metric from the pres. shell.
   101   int32_t pressedButtonAction;
   102   if (NS_FAILED(LookAndFeel::GetInt(tmpAction, &pressedButtonAction))) {
   103     return false;
   104   }
   106   // get the scrollbar control
   107   nsIFrame* scrollbar;
   108   GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
   110   if (scrollbar == nullptr)
   111     return false;
   113   // get the scrollbars content node
   114   nsIContent* content = scrollbar->GetContent();
   116   static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment,
   117                                                    &nsGkAtoms::decrement,
   118                                                    nullptr };
   119   int32_t index = mContent->FindAttrValueIn(kNameSpaceID_None,
   120                                             nsGkAtoms::type,
   121                                             strings, eCaseMatters);
   122   int32_t direction;
   123   if (index == 0) 
   124     direction = 1;
   125   else if (index == 1)
   126     direction = -1;
   127   else
   128     return false;
   130   // Whether or not to repeat the click action.
   131   bool repeat = true;
   132   // Use smooth scrolling by default.
   133   bool smoothScroll = true;
   134   switch (pressedButtonAction) {
   135     case 0:
   136       mIncrement = direction * nsSliderFrame::GetIncrement(content);
   137       break;
   138     case 1:
   139       mIncrement = direction * nsSliderFrame::GetPageIncrement(content);
   140       break;
   141     case 2:
   142       if (direction == -1)
   143         mIncrement = -nsSliderFrame::GetCurrentPosition(content);
   144       else
   145         mIncrement = nsSliderFrame::GetMaxPosition(content) - 
   146                      nsSliderFrame::GetCurrentPosition(content);
   147       // Don't repeat or use smooth scrolling if scrolling to beginning or end
   148       // of a page.
   149       repeat = smoothScroll = false;
   150       break;
   151     case 3:
   152     default:
   153       // We were told to ignore this click, or someone assigned a non-standard
   154       // value to the button's action.
   155       return false;
   156   }
   157   // set this attribute so we can style it later
   158   nsWeakFrame weakFrame(this);
   159   mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true);
   161   nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED);
   163   if (weakFrame.IsAlive()) {
   164     DoButtonAction(smoothScroll);
   165   }
   166   if (repeat)
   167     StartRepeat();
   168   return true;
   169 }
   171 NS_IMETHODIMP 
   172 nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
   173                                       WidgetGUIEvent* aEvent,
   174                                       nsEventStatus* aEventStatus)
   175 {
   176   nsIPresShell::SetCapturingContent(nullptr, 0);
   177   // we're not active anymore
   178   mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, true);
   179   StopRepeat();
   180   return NS_OK;
   181 }
   183 void nsScrollbarButtonFrame::Notify()
   184 {
   185   // Since this is only going to get called if we're scrolling a page length
   186   // or a line increment, we will always use smooth scrolling.
   187   if (mCursorOnThis ||
   188       LookAndFeel::GetInt(
   189         LookAndFeel::eIntID_ScrollbarButtonAutoRepeatBehavior, 0)) {
   190     DoButtonAction(true);
   191   }
   192 }
   194 void
   195 nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext,
   196                                      WidgetGUIEvent* aEvent) 
   197 {
   198   nsButtonBoxFrame::MouseClicked(aPresContext, aEvent);
   199   //MouseClicked();
   200 }
   202 void
   203 nsScrollbarButtonFrame::DoButtonAction(bool aSmoothScroll) 
   204 {
   205   // get the scrollbar control
   206   nsIFrame* scrollbar;
   207   GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
   209   if (scrollbar == nullptr)
   210     return;
   212   // get the scrollbars content node
   213   nsCOMPtr<nsIContent> content = scrollbar->GetContent();
   215   // get the current pos
   216   int32_t curpos = nsSliderFrame::GetCurrentPosition(content);
   217   int32_t oldpos = curpos;
   219   // get the max pos
   220   int32_t maxpos = nsSliderFrame::GetMaxPosition(content);
   222   // increment the given amount
   223   if (mIncrement)
   224     curpos += mIncrement;
   226   // make sure the current position is between the current and max positions
   227   if (curpos < 0)
   228     curpos = 0;
   229   else if (curpos > maxpos)
   230     curpos = maxpos;
   232   nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
   233   if (sb) {
   234     nsIScrollbarMediator* m = sb->GetScrollbarMediator();
   235     if (m) {
   236       m->ScrollbarButtonPressed(sb, oldpos, curpos);
   237       return;
   238     }
   239   }
   241   // set the current position of the slider.
   242   nsAutoString curposStr;
   243   curposStr.AppendInt(curpos);
   245   if (aSmoothScroll)
   246     content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
   247   content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, true);
   248   if (aSmoothScroll)
   249     content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
   250 }
   252 nsresult
   253 nsScrollbarButtonFrame::GetChildWithTag(nsPresContext* aPresContext,
   254                                         nsIAtom* atom, nsIFrame* start,
   255                                         nsIFrame*& result)
   256 {
   257   // recursively search our children
   258   nsIFrame* childFrame = start->GetFirstPrincipalChild();
   259   while (nullptr != childFrame) 
   260   {    
   261     // get the content node
   262     nsIContent* child = childFrame->GetContent();
   264     if (child) {
   265       // see if it is the child
   266        if (child->Tag() == atom)
   267        {
   268          result = childFrame;
   270          return NS_OK;
   271        }
   272     }
   274      // recursive search the child
   275      GetChildWithTag(aPresContext, atom, childFrame, result);
   276      if (result != nullptr) 
   277        return NS_OK;
   279     childFrame = childFrame->GetNextSibling();
   280   }
   282   result = nullptr;
   283   return NS_OK;
   284 }
   286 nsresult
   287 nsScrollbarButtonFrame::GetParentWithTag(nsIAtom* toFind, nsIFrame* start,
   288                                          nsIFrame*& result)
   289 {
   290    while (start)
   291    {
   292       start = start->GetParent();
   294       if (start) {
   295         // get the content node
   296         nsIContent* child = start->GetContent();
   298         if (child && child->Tag() == toFind) {
   299           result = start;
   300           return NS_OK;
   301         }
   302       }
   303    }
   305    result = nullptr;
   306    return NS_OK;
   307 }
   309 void
   310 nsScrollbarButtonFrame::DestroyFrom(nsIFrame* aDestructRoot)
   311 {
   312   // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
   313   // from under you while you're in the process of scrolling.
   314   StopRepeat();
   315   nsButtonBoxFrame::DestroyFrom(aDestructRoot);
   316 }

mercurial