WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
patch v2
0001-Spatial-Navigation-make-it-work-with-focusable-elem.patch (text/plain), 24.14 KB, created by
Antonio Gomes
on 2010-04-18 20:22:00 PDT
(
hide
)
Description:
patch v2
Filename:
MIME Type:
Creator:
Antonio Gomes
Created:
2010-04-18 20:22:00 PDT
Size:
24.14 KB
patch
obsolete
>From bb4cf4681eb2332a5c18c07bd9ede46af8429779 Mon Sep 17 00:00:00 2001 >From: Antonio Gomes <tonikitoo@webkit.org> >Date: Mon, 12 Apr 2010 14:46:34 -0400 >Subject: [PATCH] Spatial Navigation: make it work with focusable elements in overflow content > https://bugs.webkit.org/show_bug.cgi?id=36463 > >Reviewed by NOBODY (OOPS!). >Patch by Antonio Gomes <tonikitoo@webkit.org> > >WebCore: > >Test: fast/events/spatial-navigation/snav-content-overflow.html > >* page/FocusController.cpp: >(WebCore::updateFocusCandidateIfCloser): >(WebCore::FocusController::findFocusableNodeInDirection): >* page/SpatialNavigation.cpp: >(WebCore::renderRectRelativeToRootDocument): >* page/SpatialNavigation.h: >(WebCore::FocusCandidate::FocusCandidate): > >LayoutTests: > >* fast/events/spatial-navigation/snav-content-overflow-expected.txt: Added. >* fast/events/spatial-navigation/snav-content-overflow.html: Added. >--- > LayoutTests/ChangeLog | 10 + > .../snav-content-overflow-expected.txt | 31 +++ > .../spatial-navigation/snav-content-overflow.html | 120 ++++++++++++ > WebCore/ChangeLog | 17 ++ > WebCore/page/FocusController.cpp | 196 +++++++++++++++----- > WebCore/page/FocusController.h | 5 +- > WebCore/page/SpatialNavigation.cpp | 10 +- > WebCore/page/SpatialNavigation.h | 3 + > 8 files changed, 335 insertions(+), 57 deletions(-) > create mode 100644 LayoutTests/fast/events/spatial-navigation/snav-content-overflow-expected.txt > create mode 100644 LayoutTests/fast/events/spatial-navigation/snav-content-overflow.html > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index dc61559..40974bf 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1501,6 +1501,16 @@ > > Reviewed by Simon Fraser. > >+ Spatial Navigation: make it work with focusable elements in overflow content >+ https://bugs.webkit.org/show_bug.cgi?id=36463 >+ >+ * fast/events/spatial-navigation/snav-content-overflow-expected.txt: Added. >+ * fast/events/spatial-navigation/snav-content-overflow.html: Added. >+ >+2010-04-12 Antonio Gomes <tonikitoo@webkit.org> >+ >+ Reviewed by NOBODY (OOPS!). >+ > Spatial Navigation: make renderRectRelativeToRootDocument method to fallback to getRect() of Element when needed > https://bugs.webkit.org/show_bug.cgi?id=37461 > >diff --git a/LayoutTests/fast/events/spatial-navigation/snav-content-overflow-expected.txt b/LayoutTests/fast/events/spatial-navigation/snav-content-overflow-expected.txt >new file mode 100644 >index 0000000..147062f >--- /dev/null >+++ b/LayoutTests/fast/events/spatial-navigation/snav-content-overflow-expected.txt >@@ -0,0 +1,31 @@ >+Link_1 is a normal link. >+ >+Below is a scrollable Div created with the CSS property overflow. >+ >+It has a visible link_2. >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+ >+... and an overflowed link like this. >+ >+And this is another normal link_3. >+ >+PASS document.activeElement.getAttribute("id") is "1" >+PASS document.activeElement.getAttribute("id") is "2" >+PASS document.activeElement.getAttribute("id") is "3" >+PASS document.activeElement.getAttribute("id") is "2" >+PASS document.activeElement.getAttribute("id") is "1" >+PASS document.activeElement.getAttribute("id") is "start" >+ >diff --git a/LayoutTests/fast/events/spatial-navigation/snav-content-overflow.html b/LayoutTests/fast/events/spatial-navigation/snav-content-overflow.html >new file mode 100644 >index 0000000..e4b511b >--- /dev/null >+++ b/LayoutTests/fast/events/spatial-navigation/snav-content-overflow.html >@@ -0,0 +1,120 @@ >+<html> >+ <!-- >+ This test ensures the content overflow traversal correctness of Spatial Navigation >+ algorithm: focusable elements in scrollable containers (e.g. <div>) should be >+ accessible, including offscreen content. >+ >+ * Pre-conditions: >+ 1) DRT support for SNav enable/disable. >+ >+ * Navigation steps: >+ 1) Loads this page, focus goes to "start" automatically. >+ 2) Move focus down to the visible focusable element in >+ scrollable div. >+ 3) Traverse the page through other focusable elements down the page. >+ and then back up. >+ >+ * Expected results: All focusable element in scrollable content, including >+ offscreen ones, should be accessible via SNav. --> >+ <head> >+ <style type="text/css"> >+ div.scroll { >+ height: 200px; >+ width: 300px; >+ overflow: auto; >+ border: 1px solid #666; >+ background-color: #ccc; >+ padding: 8px; >+ } >+ </style> >+ >+ <script src="../../js/resources/js-test-pre.js"></script> >+ <script src="resources/spatial-navigation-utils.js"></script> >+ <script type="application/javascript"> >+ >+ var resultMap1 = [ >+ ["Down", "1"], >+ ["", ""] >+ ]; >+ >+ var resultMap2 = [ >+ ["Down", "2"], >+ ["Down", "3"], >+ ["Up", "2"], >+ ["", ""] >+ ]; >+ >+ var resultMap3 = [ >+ ["Up", "1"], >+ ["Up", "start"], >+ ["DONE", "DONE"] >+ ] >+ >+ if (window.layoutTestController) { >+ layoutTestController.dumpAsText(); >+ layoutTestController.setSpatialNavigationEnabled(true); >+ layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1); >+ layoutTestController.waitUntilDone(); >+ } >+ >+ function runTest() >+ { >+ // starting the test itself: get to a known place. >+ document.getElementById("start").focus(); >+ >+ setTimeout(step1, 0); >+ setTimeout(step2, 50); >+ setTimeout(step3, 150); >+ } >+ >+ function step1() >+ { >+ // Actions in 'resultMap1' should keep the focus in the currently >+ // focused element ('start') once the best candidate ('end') is not >+ // visible in current viewport. >+ initTest(resultMap1); >+ } >+ >+ function step2() >+ { >+ // Then it scrolls down to the end of the div ... >+ if (window.eventSender) >+ eventSender.keyDown("end"); >+ >+ // And 'resultMap2' re-tries to move focus down. >+ initTest(resultMap2); >+ } >+ >+ function step3() >+ { >+ // Then it scrolls back up the div ... >+ if (window.eventSender) >+ eventSender.keyDown("home"); >+ >+ initTest(resultMap3, testCompleted); >+ } >+ >+ function testCompleted() >+ { >+ if (window.layoutTestController) >+ layoutTestController.notifyDone(); >+ } >+ >+ window.onload = runTest; >+ >+ </script> >+ <script src="../js/resources/js-test-post.js"></script> >+ </head> >+ >+ <body id="some-content" xmlns="http://www.w3.org/1999/xhtml"> >+ <p><a id="start" href="a">Link_1</a> is a normal link.</p> >+ <p>Below is a scrollable Div created with the CSS property overflow.</p> >+ <div class="scroll"> >+ <p>It has a visible <a id="1" href="a">link_2</a>.</p> >+ <br><br><br><br><br><br><br><br><br><br><br><br><br><br> >+ <p>... and an overflowed link like <a id="2" href="a">this</a>.</p> >+ </div> >+ <p>And this is another normal <a id="3" href="a">link_3</a>.</p> >+ <div id="console"></div> >+ </body> >+</html> >diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog >index c8ebaae..52dc334 100644 >--- a/WebCore/ChangeLog >+++ b/WebCore/ChangeLog >@@ -1,3 +1,20 @@ >+2010-04-12 Antonio Gomes <tonikitoo@webkit.org> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Spatial Navigation: make it work with focusable elements in overflow content >+ https://bugs.webkit.org/show_bug.cgi?id=36463 >+ >+ Test: fast/events/spatial-navigation/snav-content-overflow.html >+ >+ * page/FocusController.cpp: >+ (WebCore::updateFocusCandidateIfCloser): >+ (WebCore::FocusController::findFocusableNodeInDirection): >+ * page/SpatialNavigation.cpp: >+ (WebCore::renderRectRelativeToRootDocument): >+ * page/SpatialNavigation.h: >+ (WebCore::FocusCandidate::FocusCandidate): >+ > 2010-04-17 Alexey Proskuryakov <ap@apple.com> > > Reviewed by Adam Barth. >diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp >index 6db9ef4..f1a5c71 100644 >--- a/WebCore/page/FocusController.cpp >+++ b/WebCore/page/FocusController.cpp >@@ -305,7 +305,7 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa > frame = frame->tree()->top(); > > FocusCandidate focusCandidate; >- findFocusableNodeInDirection(frame->document(), focusedNode, direction, event, focusCandidate); >+ findFocusableNodeInDirection(frame->document()->firstChild(), focusedNode, direction, event, focusCandidate); > > Node* node = focusCandidate.node; > if (!node || !node->isElementNode()) { >@@ -345,14 +345,42 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa > // FIXME: Make this method more modular, and simpler to understand and maintain. > static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate& candidate, FocusCandidate& closest) > { >- bool sameDocument = candidate.document() == closest.document(); >- if (sameDocument) { >- if (closest.alignment > candidate.alignment >- || (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) >+ bool sameContainer; >+ if (candidate.document() != closest.document()) >+ sameContainer = false; >+ else >+ sameContainer = !(candidate.enclosingScrollableBox != closest.enclosingScrollableBox); >+ >+ if (closest.alignment > candidate.alignment) { >+ >+ if (sameContainer) > return; >- } else if (closest.alignment > candidate.alignment >- && (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) >- return; >+ >+ if (candidate.parentAlignment && candidate.parentAlignment < closest.alignment) >+ return; >+ >+ } else if (closest.alignment < candidate.alignment) { >+ >+ if (!sameContainer) >+ if (closest.parentAlignment && candidate.parentAlignment) >+ if (closest.parentDistance < candidate.parentDistance) >+ return; >+ >+ } else { >+ >+ // We would generally just bail out if candidate's distance is larger than that >+ // of the closest candidate, however, there are scrollable overflowed content conditions >+ // involved to be checked first: >+ if (candidate.distance >= closest.distance) { >+ // 1) If the candidate is not in a scrollable container; >+ // 2) If the current candidate and the closest are in the same scrollable container; >+ // 3) If the candidate is in a scrollable container but the current focused node is not. >+ if (!candidate.enclosingScrollableBox >+ || candidate.enclosingScrollableBox == closest.enclosingScrollableBox >+ || (candidate.enclosingScrollableBox && !focusedNode->isDescendantOf(candidate.enclosingScrollableBox))) >+ return; >+ } >+ } > > if (candidate.alignment != None > || (closest.parentAlignment >= candidate.alignment >@@ -362,25 +390,45 @@ static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate > // distance so we force it to be bigger than any result we will get from > // spatialDistance(). > if (closest.alignment < candidate.alignment >- && closest.parentAlignment < candidate.alignment) >+ && closest.parentAlignment < candidate.alignment >+ && closest.enclosingScrollableBox == candidate.enclosingScrollableBox) > closest.distance = maxDistance(); > } > >- // Bail out if candidate's distance is larger than that of the closest candidate. >- if (candidate.distance >= closest.distance) >- return; >- > if (closest.isNull()) { > closest = candidate; > return; > } > >- // If the focused node and the candadate are in the same document and current >- // closest candidate is not in an {i}frame that is preferable to get focused ... >- if (focusedNode->document() == candidate.document() >- && candidate.distance < closest.parentDistance) >- closest = candidate; >- else if (focusedNode->document() != candidate.document()) { >+ // If the focused node and the candidate are in the same document: >+ if (focusedNode->document() == candidate.document()) { >+ >+ // First, check for the common case: focus candidate is *not* in a scrollable container. >+ if (!candidate.enclosingScrollableBox) { >+ if (candidate.distance < closest.parentDistance) { >+ if (!closest.enclosingScrollableBox) >+ closest = candidate; >+ >+ else if (closest.enclosingScrollableBox == candidate.enclosingScrollableBox) >+ closest = candidate; >+ } >+ >+ } else { >+ // When it is in a scrollable container, then: >+ // #1 - check if current focused node is in the same enclosing scrollable >+ // box than candidate. >+ if (focusedNode->isDescendantOf(candidate.enclosingScrollableBox)) { >+ if (candidate.enclosingScrollableBox != closest.enclosingScrollableBox) >+ closest = candidate; >+ >+ else if (candidate.distance < closest.distance) >+ closest = candidate; >+ >+ // #2 - Or only the spatial distance is enough. >+ } else if (candidate.distance < closest.distance) >+ closest = candidate; >+ } >+ } else { > // If the focusedNode is in an inner document and candidate is in a > // different document, we only consider to change focus if there is not > // another already good focusable candidate in the same document as focusedNode. >@@ -390,67 +438,113 @@ static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate > } > } > >-void FocusController::findFocusableNodeInDirection(Document* document, Node* focusedNode, >+void FocusController::findFocusableNodeInDirection(Node* outter, Node* focusedNode, > FocusDirection direction, KeyboardEvent* event, > FocusCandidate& closestFocusCandidate, > const FocusCandidate& candidateParent) > { >- ASSERT(document); >- ASSERT(candidateParent.isNull() || static_cast<HTMLFrameOwnerElement*>(candidateParent.node)); >+ ASSERT(outter); >+ ASSERT(candidateParent.isNull() || container->hasTagName(frameTag) || container->hasTagName(iframeTag) || container->hasTagName(divTag)); > > // Walk all the child nodes and update closestFocusCandidate if we find a nearer node. >- for (Node* candidate = document->firstChild(); candidate; candidate = candidate->traverseNextNode()) { >+ Node* candidate = outter; >+ while (candidate) { >+ >+ // Scrollable containers (e.g. <div>) case. >+ if (candidate->hasTagName(divTag)) { >+ RenderObject* renderer = candidate->renderer(); >+ if(renderer && renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) { >+ deepFindFocusableNodeInDirection(candidate, focusedNode, direction, event, closestFocusCandidate); >+ candidate = candidate->traverseNextSibling(); >+ continue; >+ } > // Inner documents case. >+ } else if (candidate->isFrameOwnerElement()) { >+ deepFindFocusableNodeInDirection(candidate, focusedNode, direction, event, >+ closestFocusCandidate); >+ >+ } else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { > >- if (candidate->isFrameOwnerElement()) >- deepFindFocusableNodeInDirection(focusedNode, candidate, direction, event, closestFocusCandidate); >- else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { > FocusCandidate currentFocusCandidate(candidate); > >+ // There are two ways to identify we are in a recursive call from deepFindFocusableNodeInDirection >+ // (i.e. processing an element in an iframe, frame or a scrollable div): >+ >+ // 1) If candidateParent is not null, and it holds the distance and alignment data of the >+ // parent container element itself. >+ if (!candidateParent.isNull()) { >+ currentFocusCandidate.parentAlignment = candidateParent.alignment; >+ currentFocusCandidate.parentDistance = candidateParent.distance; >+ currentFocusCandidate.enclosingScrollableBox = candidateParent.node; >+ >+ // 2) Parent of outter is either a div, a frame or an iframe tag. >+ } else if (outter->parent()->hasTagName(divTag) || !isInRootDocument(outter)) >+ currentFocusCandidate.enclosingScrollableBox = outter->parent(); >+ > // Get distance and alignment from current candidate. > distanceDataForNode(direction, focusedNode, currentFocusCandidate); > > // Bail out if distance is maximum. >- if (currentFocusCandidate.distance == maxDistance()) >+ if (currentFocusCandidate.distance == maxDistance()) { >+ candidate = candidate->traverseNextNode(outter->parent()); > continue; >- >- // If candidateParent is not null, it means that we are in a recursive call >- // from deepFineFocusableNodeInDirection (i.e. processing an element in an iframe), >- // and holds the distance and alignment data of the iframe element itself. >- if (!candidateParent.isNull()) { >- currentFocusCandidate.parentAlignment = candidateParent.alignment; >- currentFocusCandidate.parentDistance = candidateParent.distance; > } > > updateFocusCandidateIfCloser(focusedNode, currentFocusCandidate, closestFocusCandidate); > } >+ >+ candidate = candidate->traverseNextNode(outter->parent()); > } > } > >-void FocusController::deepFindFocusableNodeInDirection(Node* focusedNode, Node* candidate, >+void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode, > FocusDirection direction, KeyboardEvent* event, > FocusCandidate& closestFocusCandidate) > { >- HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(candidate); >- if (!owner->contentFrame()) >+ ASSERT(container->hasTagName(frameTag) || container->hasTagName(iframeTag) || container->hasTagName(divTag)); >+ >+ // Track if focusedNode is a descendant or not of the current container node being processed. >+ bool descendantOfContainer = false; >+ Node* firstChild = 0; >+ >+ // Iframe or Frame. >+ if (container->hasTagName(frameTag) || container->hasTagName(iframeTag)) { >+ >+ HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(container); >+ if (!owner->contentFrame()) >+ return; >+ >+ Document* innerDocument = owner->contentFrame()->document(); >+ if (!innerDocument) >+ return; >+ >+ descendantOfContainer = innerDocument == focusedNode->document(); >+ firstChild = innerDocument->firstChild(); >+ >+ // Scrollable div. >+ } else if (container->hasTagName(divTag)) { >+ >+ firstChild = container->firstChild(); >+ descendantOfContainer = focusedNode->isDescendantOf(container); >+ } >+ >+ if (descendantOfContainer) { >+ findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate); > return; >+ } > >- Document* innerDocument = owner->contentFrame()->document(); >- if (!innerDocument) >+ // Check if the current container element itself is a good candidate >+ // to move focus to. If it is, then we traverse its inner nodes. >+ FocusCandidate candidateParent = FocusCandidate(container); >+ distanceDataForNode(direction, focusedNode, candidateParent); >+ >+ // Bail out if distance is maximum. >+ if (candidateParent.distance == maxDistance()) > return; > >- if (innerDocument == focusedNode->document()) >- findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate); >- else { >- // Check if the current {i}frame element itself is a good candidate >- // to move focus to. If it is, then we traverse its inner nodes. >- FocusCandidate candidateParent = FocusCandidate(candidate); >- distanceDataForNode(direction, focusedNode, candidateParent); >- >- // FIXME: Consider alignment? >- if (candidateParent.distance < closestFocusCandidate.distance) >- findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate, candidateParent); >- } >+ // FIXME: Consider alignment? >+ if (candidateParent.distance < closestFocusCandidate.distance) >+ findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate, candidateParent); > } > > static bool relinquishesEditingFocus(Node *node) >diff --git a/WebCore/page/FocusController.h b/WebCore/page/FocusController.h >index dfa3780..4410833 100644 >--- a/WebCore/page/FocusController.h >+++ b/WebCore/page/FocusController.h >@@ -63,9 +63,10 @@ private: > bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*); > bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus); > >- void findFocusableNodeInDirection(Document*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate& closestFocusCandidate, >+ void findFocusableNodeInDirection(Node* outter, Node*, FocusDirection, KeyboardEvent*, >+ FocusCandidate& closestFocusCandidate, > const FocusCandidate& parentCandidate = FocusCandidate()); >- void deepFindFocusableNodeInDirection(Node*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate&); >+ void deepFindFocusableNodeInDirection(Node* container, Node* focused, FocusDirection, KeyboardEvent*, FocusCandidate&); > > Page* m_page; > RefPtr<Frame> m_focusedFrame; >diff --git a/WebCore/page/SpatialNavigation.cpp b/WebCore/page/SpatialNavigation.cpp >index 9bb903d..445280e 100644 >--- a/WebCore/page/SpatialNavigation.cpp >+++ b/WebCore/page/SpatialNavigation.cpp >@@ -95,6 +95,7 @@ void distanceDataForNode(FocusDirection direction, Node* start, FocusCandidate& > // The distance between two nodes is not to be considered alone when evaluating/looking > // for the best focus candidate node. Alignment of rects can be also a good point to be > // considered in order to make the algorithm to behavior in a more intuitive way. >+ > candidate.alignment = alignmentForRects(direction, curRect, targetRect); > candidate.distance = spatialDistance(direction, curRect, targetRect); > } >@@ -114,12 +115,13 @@ static IntRect renderRectRelativeToRootDocument(RenderObject* render) > // document, we only consider its scrollOffset if it is not offscreen. > Node* node = render->node(); > Document* mainDocument = node->document()->page()->mainFrame()->document(); >+ > bool considerScrollOffset = !hasOffscreenRect(node) && node->document() != mainDocument; > >- if (considerScrollOffset) { >- if (FrameView* frameView = render->node()->document()->view()) >- rect.move(-frameView->scrollOffset()); >- } >+ if (considerScrollOffset) { >+ if (FrameView* frameView = render->node()->document()->view()) >+ rect.move(-frameView->scrollOffset()); >+ } > > // Handle nested frames. > for (Frame* frame = render->document()->frame(); frame; frame = frame->tree()->parent()) { >diff --git a/WebCore/page/SpatialNavigation.h b/WebCore/page/SpatialNavigation.h >index df0acb4..6da1bba 100644 >--- a/WebCore/page/SpatialNavigation.h >+++ b/WebCore/page/SpatialNavigation.h >@@ -98,6 +98,7 @@ enum RectsAlignment { > struct FocusCandidate { > FocusCandidate() > : node(0) >+ , enclosingScrollableBox(0) > , distance(maxDistance()) > , parentDistance(maxDistance()) > , alignment(None) >@@ -107,6 +108,7 @@ struct FocusCandidate { > > FocusCandidate(Node* n) > : node(n) >+ , enclosingScrollableBox(0) > , distance(maxDistance()) > , parentDistance(maxDistance()) > , alignment(None) >@@ -118,6 +120,7 @@ struct FocusCandidate { > Document* document() const { return node ? node->document() : 0; } > > Node* node; >+ Node* enclosingScrollableBox; > long long distance; > long long parentDistance; > RectsAlignment alignment; >-- >1.6.0.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 36463
:
51364
|
51954
|
53183
|
53652
|
53683
|
56073
|
56402
|
56483
|
56880
|
56882
|
58640
|
58644
|
58773