diff options
Diffstat (limited to 'WebKit/android/nav/CacheBuilder.cpp')
| -rw-r--r-- | WebKit/android/nav/CacheBuilder.cpp | 211 |
1 files changed, 105 insertions, 106 deletions
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index 4acf598..f854e71 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -13,7 +13,7 @@ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 APPLE COMPUTER, INC. OR + * 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 @@ -42,6 +42,7 @@ #include "HTMLNames.h" #include "HTMLOptionElement.h" #include "HTMLSelectElement.h" +#include "HTMLTextAreaElement.h" #include "InlineTextBox.h" #include "KURL.h" #include "PluginView.h" @@ -93,14 +94,11 @@ Frame* CacheBuilder::FrameAnd(const CacheBuilder* cacheBuilder) { #if DUMP_NAV_CACHE static bool hasEventListener(Node* node, const AtomicString& eventType) { - const RegisteredEventListenerVector& listeners = node->eventListeners(); - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listeners[i]; - if (r.eventType() == eventType) - return true; - } - return false; + if (!node->isElementNode()) + return false; + Element* element = static_cast<Element*>(node); + EventListener* listener = element->getAttributeEventListener(eventType); + return 0 != listener; } #define DEBUG_BUFFER_SIZE 256 @@ -143,7 +141,9 @@ void CacheBuilder::Debug::flush() { break; len++; } - while (mBuffer[len] == '\\' || mBuffer[len] == '"') + while (len > 0 && mBuffer[len - 1] == '\\') + len--; + while (mBuffer[len] == '"') len++; } const char* prefix = mPrefix; @@ -349,8 +349,11 @@ void CacheBuilder::Debug::groups() { } while ((node = node->traverseNextNode()) != NULL); int focusIndex = -1; if (atLeastOne == false) { - DUMP_NAV_LOGD("#define TEST%s_RECTS NULL\n", name); - DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = 0; // no focusable nodes\n", name); + DUMP_NAV_LOGD("static DebugTestNode TEST%s_RECTS[] = {\n" + "{{0, 0, 0, 0}, \"\", 0, -1, \"\", {0, 0, 0, 0}, false, 0}\n" + "};\n\n", name); + DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = 1;" + " // no focusable nodes\n", name); DUMP_NAV_LOGD("#define TEST%s_RECTPARTS NULL\n", name); } else { node = doc; @@ -435,6 +438,7 @@ void CacheBuilder::Debug::groups() { snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s" ", %d},",absB.x(), absB.y(), absB.width(), absB.height(), renderer->hasOverflowClip() ? "true" : "false", tabindex); + // TODO: add renderer->style()->visibility() print(scratch); } else print(", {0, 0, 0, 0}, false, 0},"); @@ -547,7 +551,7 @@ void CacheBuilder::Debug::groups() { int contentsHeight = layer->height(); DUMP_NAV_LOGD("static int TEST%s_FOCUS = %d;\n", name, focusIndex); DUMP_NAV_LOGD("static int TEST%s_WIDTH = %d;\n", name, contentsWidth); - DUMP_NAV_LOGD("static int TEST%s_HEIGHT = %d;\n", name, contentsHeight); + DUMP_NAV_LOGD("static int TEST%s_HEIGHT = %d;\n\n", name, contentsHeight); } bool CacheBuilder::Debug::isFocusable(Node* node) { @@ -721,7 +725,7 @@ void CacheBuilder::Debug::wideString(const String& str) { CacheBuilder::CacheBuilder() { - mAllowableTypes = ALL_CACHEDNODETYPES; + mAllowableTypes = ALL_CACHEDNODE_BITS; #ifdef DUMP_NAV_CACHE_USING_PRINTF gNavCacheLogFile = NULL; #endif @@ -756,14 +760,9 @@ void CacheBuilder::adjustForColumns(const ClipColumnTracker& track, // Checks if a node has one of event listener types. bool CacheBuilder::NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length) { - const RegisteredEventListenerVector& listeners = node->eventListeners(); - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listeners[i]; - for (int j = 0; j < length; ++j) { - if (r.eventType() == eventTypes[j]) - return true; - } + for (int i = 0; i < length; ++i) { + if (!node->getEventListeners(eventTypes[i]).isEmpty()) + return true; } return false; } @@ -825,6 +824,16 @@ void CacheBuilder::buildCache(CachedRoot* root) setData((CachedFrame*) root); } +static Node* ParentWithChildren(Node* node) +{ + Node* parent = node; + while ((parent = parent->parentNode())) { + if (parent->childNodeCount() > 1) + return parent; + } + return 0; +} + static Node* OneAfter(Node* node) { Node* parent = node; @@ -900,6 +909,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedFrame->add(cachedParentNode); Node* node = parent; int cacheIndex = 1; + int textInputIndex = 0; Node* focused = doc->focusedNode(); if (focused) cachedRoot->setFocusBounds(focused->getRect()); @@ -918,8 +928,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, lastChildIndex = last->mCachedNodeIndex; last = &tracker.last(); } - if (node == last->mParentLastChild) - last->mParentLastChild = NULL; do { const ClipColumnTracker* lastClip = &clipTracker.last(); if (node != lastClip->mLastChild) @@ -946,7 +954,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedFrame->addFrame(cachedChild); cachedNode.init(node); cachedNode.setIndex(cacheIndex++); - cachedNode.setChildFrameIndex(childFrameIndex); + cachedNode.setDataIndex(childFrameIndex); + cachedNode.setType(FRAME_CACHEDNODETYPE); #if DUMP_NAV_CACHE cachedNode.mDebug.mNodeIndex = nodeIndex; cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex( @@ -986,27 +995,19 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, bool computeCursorRings = false; bool hasClip = false; bool hasMouseOver = false; - bool isAnchor = false; - bool isArea = node->hasTagName(HTMLNames::areaTag); - bool isPassword = false; - bool isTextArea = false; - bool isTextField = false; - bool isRtlText = false; bool isUnclipped = false; bool isFocus = node == focused; bool takesFocus = false; - bool wantsKeyEvents = false; - int maxLength = -1; - int textSize = 12; int columnGap = 0; TextDirection direction = LTR; - String name; String exported; CachedNodeType type = NORMAL_CACHEDNODETYPE; + CachedInput cachedInput; IntRect bounds; IntRect absBounds; WTF::Vector<IntRect>* columns = NULL; - if (isArea) { + if (node->hasTagName(HTMLNames::areaTag)) { + type = AREA_CACHEDNODETYPE; HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); bounds = getAreaRect(area); bounds.move(globalOffsetX, globalOffsetY); @@ -1028,7 +1029,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, bounds = absBounds; isUnclipped = true; takesFocus = true; - wantsKeyEvents = true; + type = PLUGIN_CACHEDNODETYPE; goto keepNode; } if (nodeRenderer->isRenderBlock()) { @@ -1052,11 +1053,11 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, clip.mHasClip = hasClip; clip.mDirection = direction; if (columns != NULL) { - const IntRect& oRect = ((RenderBox*)nodeRenderer)->overflowRect(true); + const IntRect& oRect = ((RenderBox*)nodeRenderer)->visibleOverflowRect(); clip.mBounds.move(oRect.x(), oRect.y()); } } - if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODETYPE) { + if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODE_BITS) { if (last->mSomeParentTakesFocus) // don't look at text inside focusable node continue; CachedNodeType checkType; @@ -1072,7 +1073,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, DUMP_NAV_LOGD("%s\n", buffer); } #endif - type = (CachedNodeType) checkType; + type = checkType; // !!! test ! is the following line correctly needed for frames to work? cachedNode.init(node); const ClipColumnTracker& clipTrack = clipTracker.last(); @@ -1096,18 +1097,35 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } if (node->hasTagName(WebCore::HTMLNames::inputTag)) { HTMLInputElement* input = (HTMLInputElement*) node; - if (input->inputType() == HTMLInputElement::FILE) + HTMLInputElement::InputType inputType = input->inputType(); + if (input->isTextField()) { + type = TEXT_INPUT_CACHEDNODETYPE; + cachedInput.init(); + cachedInput.setFormPointer(input->form()); + cachedInput.setIsTextField(true); + cachedInput.setIsReadOnly(input->readOnly()); + exported = input->value().threadsafeCopy(); + cachedInput.setMaxLength(input->maxLength()); + cachedInput.setInputType(inputType); + // If this does not need to be threadsafe, we can use crossThreadString(). + // See http://trac.webkit.org/changeset/49160. + cachedInput.setName(input->name().string().threadsafeCopy()); + // can't detect if this is drawn on top (example: deviant.com login parts) + isUnclipped = isTransparent; + } else if (inputType == HTMLInputElement::HIDDEN) continue; - isTextField = input->isTextField(); - if (isTextField) - wantsKeyEvents = true; - isPassword = input->inputType() == HTMLInputElement::PASSWORD; - maxLength = input->maxLength(); - name = input->name().string().copy(); - isUnclipped = isTransparent; // can't detect if this is drawn on top (example: deviant.com login parts) - } else if (node->hasTagName(HTMLNames::textareaTag)) - isTextArea = wantsKeyEvents = true; - else if (node->hasTagName(HTMLNames::aTag)) { + } else if (node->hasTagName(HTMLNames::textareaTag)) { + cachedInput.init(); + type = TEXT_INPUT_CACHEDNODETYPE; + HTMLTextAreaElement* area = static_cast<HTMLTextAreaElement*>(node); + cachedInput.setFormPointer(area->form()); + cachedInput.setIsReadOnly(area->readOnly()); + // Although technically it is not an HTMLInputElement, and therefore + // has no InputType, this one is the most appropriate. + cachedInput.setInputType(HTMLInputElement::TEXT); + cachedInput.setIsTextField(false); + exported = area->value().threadsafeCopy(); + } else if (node->hasTagName(HTMLNames::aTag)) { const HTMLAnchorElement* anchorNode = (const HTMLAnchorElement*) node; if (!anchorNode->isFocusable() && !HasTriggerEvent(node)) @@ -1115,32 +1133,31 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, if (node->disabled()) continue; hasMouseOver = NodeHasEventListeners(node, &eventNames().mouseoverEvent, 1); - isAnchor = true; + type = ANCHOR_CACHEDNODETYPE; KURL href = anchorNode->href(); if (!href.isEmpty() && !WebCore::protocolIsJavaScript(href.string())) // Set the exported string for all non-javascript anchors. - exported = href.string().copy(); + exported = href.string().threadsafeCopy(); } - if (isTextField || isTextArea) { + if (type == TEXT_INPUT_CACHEDNODETYPE) { RenderTextControl* renderText = static_cast<RenderTextControl*>(nodeRenderer); if (isFocus) cachedRoot->setSelection(renderText->selectionStart(), renderText->selectionEnd()); - exported = renderText->text().copy(); // FIXME: Would it be better to use (float) size()? // FIXME: Are we sure there will always be a style and font, and it's correct? RenderStyle* style = nodeRenderer->style(); if (style) { isUnclipped |= !style->hasAppearance(); - textSize = style->fontSize(); - isRtlText = style->direction() == RTL || - style->textAlign() == WebCore::RIGHT || - style->textAlign() == WebCore::WEBKIT_RIGHT; + cachedInput.setTextSize(style->fontSize()); + cachedInput.setIsRtlText(style->direction() == RTL + || style->textAlign() == WebCore::RIGHT + || style->textAlign() == WebCore::WEBKIT_RIGHT); } } takesFocus = true; bounds = absBounds; - if (!isAnchor) { + if (type != ANCHOR_CACHEDNODETYPE) { bool isFocusable = node->isKeyboardFocusable(NULL) || node->isMouseFocusable() || node->isFocusable(); if (isFocusable == false) { @@ -1174,43 +1191,37 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, continue; } const IntRect& parentClip = clipTrack.mBounds; - if (hasClip == false && isAnchor) + if (hasClip == false && type == ANCHOR_CACHEDNODETYPE) clip = parentClip; else clip.intersect(parentClip); hasClip = true; } - if (hasClip && !clip.isEmpty() && cachedNode.clip(clip) == false) { - cachedNode.setBounds(clip); - cachedNode.cursorRings().append(clip); - isUnclipped = true; + if (hasClip) { + if (clip.isEmpty()) + continue; // skip this node if clip prevents all drawing + else if (cachedNode.clip(clip) == false) + continue; // skip this node if outside of the clip } cachedNode.setNavableRects(); - cachedNode.setChildFrameIndex(-1); cachedNode.setExport(exported); cachedNode.setHasCursorRing(hasCursorRing); cachedNode.setHasMouseOver(hasMouseOver); cachedNode.setHitBounds(absBounds); cachedNode.setIndex(cacheIndex); - cachedNode.setIsAnchor(isAnchor); - cachedNode.setIsArea(isArea); cachedNode.setIsFocus(isFocus); - cachedNode.setIsPassword(isPassword); - cachedNode.setIsRtlText(isRtlText); - cachedNode.setIsTextArea(isTextArea); - cachedNode.setIsTextField(isTextField); cachedNode.setIsTransparent(isTransparent); cachedNode.setIsUnclipped(isUnclipped); - cachedNode.setMaxLength(maxLength); - cachedNode.setName(name); cachedNode.setParentIndex(last->mCachedNodeIndex); - if (last->mParentLastChild == NULL) - last->mParentLastChild = OneAfter(node->parentNode()->lastChild()); - cachedNode.setParentGroup(last->mParentLastChild); + cachedNode.setParentGroup(ParentWithChildren(node)); cachedNode.setTabIndex(tabIndex); - cachedNode.setTextSize(textSize); cachedNode.setType(type); - cachedNode.setWantsKeyEvents(wantsKeyEvents); + if (type == TEXT_INPUT_CACHEDNODETYPE) { + cachedFrame->add(cachedInput); + cachedNode.setDataIndex(textInputIndex); + textInputIndex++; + } else + cachedNode.setDataIndex(-1); #if DUMP_NAV_CACHE cachedNode.mDebug.mNodeIndex = nodeIndex; cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex( @@ -1228,7 +1239,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, Tracker& working = tracker.last(); working.mCachedNodeIndex = lastIndex; working.mLastChild = OneAfter(lastChild); - working.mParentLastChild = OneAfter(node->parentNode()->lastChild()); last = &tracker.at(tracker.size() - 2); working.mSomeParentTakesFocus = last->mSomeParentTakesFocus | takesFocus; } @@ -1672,9 +1682,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars // is that suggested this fix. // if (s->mWordCount == 0 && s->mContinuationNode) // return FOUND_NONE; - s->mBases[s->mWordCount] = baseChars; - s->mWords[s->mWordCount] = chars - s->mNumberCount; - s->mStarts[s->mWordCount] = s->mCurrentStart; + s->newWord(baseChars, chars); if (WTF::isASCIILower(ch) && s->mNumberCount == 0) s->mFirstLower = chars; s->mNumberCount = 0; @@ -1722,9 +1730,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars s->mNumberWords >>= ++shift; if (s->mBases[0] != s->mBases[shift]) // if we're past the original node, bail break; - memmove(s->mBases, &s->mBases[shift], (sizeof(s->mBases) / sizeof(s->mBases[0]) - shift) * sizeof(s->mBases[0])); - memmove(s->mWords, &s->mWords[shift], (sizeof(s->mWords) / sizeof(s->mWords[0]) - shift) * sizeof(s->mWords[0])); - memmove(s->mStarts, &s->mStarts[shift], (sizeof(s->mStarts) / sizeof(s->mStarts[0]) - shift) * sizeof(s->mStarts[0])); + s->shiftWords(shift); s->mStartResult = s->mWords[0] - s->mStarts[0]; s->mWordCount -= shift; // FIXME: need to adjust lineCount to account for discarded delimiters @@ -1771,9 +1777,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars continue; if (s->mWordCount == 0 && s->mContinuationNode) return FOUND_NONE; - s->mBases[s->mWordCount] = baseChars; - s->mWords[s->mWordCount] = chars; - s->mStarts[s->mWordCount] = s->mCurrentStart; + s->newWord(baseChars, chars); s->mNumberWords |= 1 << s->mWordCount; s->mUnparsed = true; } @@ -1796,9 +1800,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars case SECOND_HALF: if (WTF::isASCIIAlpha(ch)) { if (s->mLetterCount == 0) { - s->mBases[s->mWordCount] = baseChars; - s->mWords[s->mWordCount] = chars; - s->mStarts[s->mWordCount] = s->mCurrentStart; + s->newWord(baseChars, chars); s->mWordCount++; } s->mLetterCount++; @@ -1917,9 +1919,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars s->mZipDelimiter = true; else { if (s->mLetterCount == 0) { - s->mBases[s->mWordCount] = baseChars; - s->mWords[s->mWordCount] = chars; - s->mStarts[s->mWordCount] = s->mCurrentStart; + s->newWord(baseChars, chars); s->mUnparsed = true; } ++s->mLetterCount; @@ -1990,7 +1990,8 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars goto nextTest; abbr = true; } - letter = test[testIndex]; + letter = &test[testIndex] < s->mEnds[wordsIndex] ? + test[testIndex] : ' '; if (WTF::isASCIIAlpha(letter) == false && WTF::isASCIIDigit(letter) == false) { if (s->mNumberWords != 0) { int shift = 0; @@ -2031,9 +2032,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars s->mNumberWords >>= ++shift; if (s->mBases[0] != s->mBases[shift]) return FOUND_NONE; - memmove(s->mBases, &s->mBases[shift], (sizeof(s->mBases) / sizeof(s->mBases[0]) - shift) * sizeof(s->mBases[0])); - memmove(s->mWords, &s->mWords[shift], (sizeof(s->mWords) / sizeof(s->mWords[0]) - shift) * sizeof(s->mWords[0])); - memmove(s->mStarts, &s->mStarts[shift], (sizeof(s->mStarts) / sizeof(s->mStarts[0]) - shift) * sizeof(s->mStarts[0])); + s->shiftWords(shift); s->mStartResult = s->mWords[0] - s->mStarts[0]; s->mWordCount -= shift; s->mProgress = ADDRESS_LINE; @@ -2431,7 +2430,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, CachedNodeType* type, String* exported) const { Text* textNode = static_cast<Text*>(node); - StringImpl* string = textNode->string(); + StringImpl* string = textNode->dataImpl(); const UChar* baseChars = string->characters(); // const UChar* originalBase = baseChars; int length = string->length(); @@ -2462,9 +2461,9 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, baseStart = start; for (CachedNodeType checkType = ADDRESS_CACHEDNODETYPE; checkType <= PHONE_CACHEDNODETYPE; - checkType = (CachedNodeType) (checkType << 1)) + checkType = static_cast<CachedNodeType>(checkType + 1)) { - if ((checkType & mAllowableTypes) == 0) + if ((1 << (checkType - 1) & mAllowableTypes) == 0) continue; InlineTextBox* inlineTextBox = baseInline; FindState findState; @@ -2536,7 +2535,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, exported->truncate(0); do { Text* tempText = static_cast<Text*>(temp); - StringImpl* string = tempText->string(); + StringImpl* string = tempText->dataImpl(); int end = tempText == walk->mFinalNode ? walk->mEnd : string->length(); exported->append(String(string->substring( @@ -2596,7 +2595,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, } while (renderer == NULL); baseInline = renderer->firstTextBox(); } while (baseInline == NULL); - string = nextNode->string(); + string = nextNode->dataImpl(); baseChars = string->characters(); inlineTextBox = baseInline; start = inlineTextBox->start(); @@ -2606,7 +2605,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, tryNextCheckType: node = textNode; baseInline = saveInline; - string = textNode->string(); + string = textNode->dataImpl(); baseChars = string->characters(); } if (foundBetter) { @@ -2865,7 +2864,7 @@ bool CacheBuilder::ConstructTextRect(Text* textNode, { RenderText* renderText = (RenderText*) textNode->renderer(); EVisibility vis = renderText->style()->visibility(); - StringImpl* string = textNode->string(); + StringImpl* string = textNode->dataImpl(); const UChar* chars = string->characters(); FloatPoint pt = renderText->localToAbsolute(); do { |
