COMMIT_MESSAGE

 12012-03-07 Andy Chen <andchen@rim.com>
 2
 3 Make the process of marking all matches interuptible and asynchronous for find-in-page.
 4
 5 Reviewed by NOBODY (OOPS!).
 6
 7 * WebKitSupport/InPageSearchManager.cpp:
 8 (BlackBerry::WebKit::InPageSearchManager::DeferredScopeStringMatches::DeferredScopeStringMatches):
 9 (BlackBerry::WebKit::InPageSearchManager::DeferredScopeStringMatches::doTimeout):
 10 (BlackBerry::WebKit::InPageSearchManager::findNextString):
 11 (BlackBerry::WebKit::InPageSearchManager::findAndMarkText):
 12 (BlackBerry::WebKit::InPageSearchManager::scopeStringMatches):
 13 (BlackBerry::WebKit::InPageSearchManager::scopeStringMatchesSoon):
 14 (BlackBerry::WebKit::InPageSearchManager::callScopeStringMatches):
 15 * WebKitSupport/InPageSearchManager.h:

Source/WebKit/blackberry/ChangeLog

 12012-03-12 Andy Chen <andchen@rim.com>
 2
 3 [Blackberry] Make the process of marking all matches interruptible and asynchronous for find-in-page
 4 https://bugs.webkit.org/show_bug.cgi?id=80831
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * WebKitSupport/InPageSearchManager.cpp:
 9 (BlackBerry::WebKit::InPageSearchManager::DeferredScopeStringMatches::DeferredScopeStringMatches):
 10 (BlackBerry::WebKit::InPageSearchManager::DeferredScopeStringMatches::doTimeout):
 11 (BlackBerry::WebKit::InPageSearchManager::InPageSearchManager):
 12 (BlackBerry::WebKit::InPageSearchManager::~InPageSearchManager):
 13 (BlackBerry::WebKit::InPageSearchManager::findNextString):
 14 (BlackBerry::WebKit::InPageSearchManager::shouldSearchForText):
 15 (BlackBerry::WebKit::InPageSearchManager::findAndMarkText):
 16 (BlackBerry::WebKit::InPageSearchManager::clearTextMatches):
 17 (BlackBerry::WebKit::InPageSearchManager::frameUnloaded):
 18 (BlackBerry::WebKit::InPageSearchManager::scopeStringMatches):
 19 (BlackBerry::WebKit::InPageSearchManager::scopeStringMatchesSoon):
 20 (BlackBerry::WebKit::InPageSearchManager::callScopeStringMatches):
 21 (BlackBerry::WebKit::InPageSearchManager::cancelPendingScopingEffort):
 22 * WebKitSupport/InPageSearchManager.h:
 23
1242012-03-09 Jon Lee <jonlee@apple.com>
225
326 Rename NotificationPresenter to NotificationClient

Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.cpp

2424#include "DocumentMarkerController.h"
2525#include "Editor.h"
2626#include "Frame.h"
 27#include "Node.h"
2728#include "Page.h"
 29#include "TextIterator.h"
 30#include "Timer.h"
2831#include "WebPage_p.h"
2932
30 static const int TextMatchMarkerLimit = 100;
 33static const double MaxScopingDuration = 0.1;
3134
3235using namespace WebCore;
3336
3437namespace BlackBerry {
3538namespace WebKit {
3639
 40class InPageSearchManager::DeferredScopeStringMatches {
 41public:
 42 DeferredScopeStringMatches(InPageSearchManager* ipsm, Frame* scopingFrame, const String& text, bool reset)
 43 : m_searchManager(ipsm)
 44 , m_scopingFrame(scopingFrame)
 45 , m_timer(this, &DeferredScopeStringMatches::doTimeout)
 46 , m_searchText(text)
 47 , m_reset(reset)
 48 {
 49 m_timer.startOneShot(0.0);
 50 }
 51
 52private:
 53 void doTimeout(Timer<DeferredScopeStringMatches>*)
 54 {
 55 m_searchManager->callScopeStringMatches(this, m_scopingFrame, m_searchText, m_reset);
 56 }
 57 InPageSearchManager* m_searchManager;
 58 Frame* m_scopingFrame;
 59 Timer<DeferredScopeStringMatches> m_timer;
 60 String m_searchText;
 61 bool m_reset;
 62};
 63
3764InPageSearchManager::InPageSearchManager(WebPagePrivate* page)
3865 : m_webPage(page)
3966 , m_activeMatch(0)
 67 , m_resumeScopingFromRange(0)
 68 , m_scopingComplete(false)
 69 , m_locatingActiveMatch(false)
4070{
4171}
4272
4373InPageSearchManager::~InPageSearchManager()
4474{
 75 cancelPendingScopingEffort();
4576}
4677
4778bool InPageSearchManager::findNextString(const String& text, bool forward)
4879{
4980 if (!text.length()) {
5081 clearTextMatches();
 82 cancelPendingScopingEffort();
5183 m_activeSearchString = String();
5284 return false;
5385 }

@@bool InPageSearchManager::findNextString(const String& text, bool forward)
6294 m_activeMatch = 0;
6395
6496 RefPtr<Range> searchStartingPoint(m_activeMatch);
65  if (m_activeSearchString != text) { // Start a new search.
 97 bool newSearch = m_activeSearchString != text;
 98 if (newSearch) { // Start a new search.
6699 m_activeSearchString = text;
 100 cancelPendingScopingEffort();
67101 m_webPage->m_page->unmarkAllTextMatches();
68  m_activeMatchCount = m_webPage->m_page->markAllMatchesForText(text, CaseInsensitive, true /* shouldHighlight */, TextMatchMarkerLimit);
69  if (!m_activeMatchCount) {
70  clearTextMatches();
71  return false;
72  }
73102 } else { // Search same string for next occurrence.
74103 setMarkerActive(m_activeMatch.get(), false /* active */);
75104 // Searching for same string should start from the end of last match.

@@bool InPageSearchManager::findNextString(const String& text, bool forward)
94123 | CaseInsensitive
95124 | StartInSelection;
96125
97  if (findAndMarkText(text, searchStartingPoint.get(), currentActiveMatchFrame, findOptions))
 126 if (findAndMarkText(text, searchStartingPoint.get(), currentActiveMatchFrame, findOptions, newSearch))
98127 return true;
99128
100129 Frame* startFrame = currentActiveMatchFrame;
101130 do {
102131 currentActiveMatchFrame = DOMSupport::incrementFrame(currentActiveMatchFrame, forward, true /* wrapFlag */);
103  if (findAndMarkText(text, 0, currentActiveMatchFrame, findOptions))
 132 if (findAndMarkText(text, 0, currentActiveMatchFrame, findOptions, newSearch))
104133 return true;
105134 } while (currentActiveMatchFrame && startFrame != currentActiveMatchFrame);
106135
107136 clearTextMatches();
108137
109  ASSERT_NOT_REACHED();
 138 // FIXME: We need to notify client here.
110139 return false;
111140}
112141

@@bool InPageSearchManager::shouldSearchForText(const String& text)
117146
118147 // If the previous search string is prefix of new search string,
119148 // don't search if the previous one has zero result.
120  if (!m_activeMatchCount
 149 if (m_scopingComplete
 150 && !m_activeMatchCount
121151 && m_activeSearchString.length()
122152 && text.length() > m_activeSearchString.length()
123153 && m_activeSearchString == text.substring(0, m_activeSearchString.length()))

@@bool InPageSearchManager::shouldSearchForText(const String& text)
125155 return true;
126156}
127157
128 bool InPageSearchManager::findAndMarkText(const String& text, Range* range, Frame* frame, const FindOptions& options)
 158bool InPageSearchManager::findAndMarkText(const String& text, Range* range, Frame* frame, const FindOptions& options, bool isNewSearch)
129159{
130160 m_activeMatch = frame->editor()->findStringAndScrollToVisible(text, range, options);
131161 if (m_activeMatch) {
132162 setMarkerActive(m_activeMatch.get(), true /* active */);
 163 if (isNewSearch) {
 164 scopeStringMatches(text, true /* reset */);
 165 // FIXME: If it is a not new search, we need to calculate activeMatchIndex and notify client.
 166 }
133167 return true;
134168 }
135169 return false;

@@void InPageSearchManager::clearTextMatches()
139173{
140174 m_webPage->m_page->unmarkAllTextMatches();
141175 m_activeMatch = 0;
 176 m_activeMatchCount = 0;
 177 m_activeMatchIndex = 0;
142178}
143179
144180void InPageSearchManager::setMarkerActive(Range* range, bool active)

@@void InPageSearchManager::frameUnloaded(const Frame* frame)
161197
162198 Frame* currentActiveMatchFrame = m_activeMatch->ownerDocument()->frame();
163199 if (currentActiveMatchFrame == frame) {
 200 // FIXME: We need to re-scope this frame instead of cancelling all effort?
 201 cancelPendingScopingEffort();
164202 m_activeMatch = 0;
165203 m_activeSearchString = String();
166204 m_activeMatchCount = 0;

@@void InPageSearchManager::frameUnloaded(const Frame* frame)
171209 }
172210}
173211
 212void InPageSearchManager::scopeStringMatches(const String& text, bool reset, Frame* scopingFrame)
 213{
 214 if (reset) {
 215 m_activeMatchCount = 0;
 216 m_resumeScopingFromRange = 0;
 217 m_scopingComplete = false;
 218 m_locatingActiveMatch = true;
 219 // New search should always start from mainFrame.
 220 scopeStringMatchesSoon(m_webPage->mainFrame(), text, false /* reset */);
 221 return;
 222 }
 223
 224 if (m_resumeScopingFromRange && scopingFrame != m_resumeScopingFromRange->ownerDocument()->frame())
 225 m_resumeScopingFromRange = 0;
 226
 227 RefPtr<Range> searchRange(rangeOfContents(scopingFrame->document()));
 228 Node* originalEndContainer = searchRange->endContainer();
 229 int originalEndOffset = searchRange->endOffset();
 230 ExceptionCode ec = 0, ec2 = 0;
 231 if (m_resumeScopingFromRange) {
 232 searchRange->setStart(m_resumeScopingFromRange->startContainer(), m_resumeScopingFromRange->startOffset(ec2) + 1, ec);
 233 if (ec || ec2) {
 234 m_scopingComplete = true; // We should stop scoping because of some stale data.
 235 return;
 236 }
 237 }
 238
 239 int matchCount = 0;
 240 bool timeout = false;
 241 double startTime = currentTime();
 242 do {
 243 RefPtr<Range> resultRange(findPlainText(searchRange.get(), text, CaseInsensitive));
 244 if (resultRange->collapsed(ec)) {
 245 if (!resultRange->startContainer()->isInShadowTree())
 246 break;
 247 searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), ec);
 248 searchRange->setEnd(originalEndContainer, originalEndOffset, ec);
 249 continue;
 250 }
 251
 252 if (scopingFrame->editor()->insideVisibleArea(resultRange.get())) {
 253 ++matchCount;
 254 bool foundActiveMatch = false;
 255 if (m_locatingActiveMatch && areRangesEqual(resultRange.get(), m_activeMatch.get())) {
 256 foundActiveMatch = true;
 257 m_locatingActiveMatch = false;
 258 m_activeMatchIndex = m_activeMatchCount + matchCount;
 259 // FIXME: We need to notify client with m_activeMatchIndex.
 260 }
 261 resultRange->ownerDocument()->markers()->addTextMatchMarker(resultRange.get(), foundActiveMatch);
 262 }
 263 searchRange->setStart(resultRange->endContainer(ec), resultRange->endOffset(ec), ec);
 264 Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
 265 if (searchRange->collapsed(ec) && shadowTreeRoot)
 266 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
 267 m_resumeScopingFromRange = resultRange;
 268 timeout = (currentTime() - startTime) >= MaxScopingDuration;
 269 } while (!timeout);
 270
 271 if (matchCount > 0) {
 272 scopingFrame->editor()->setMarkedTextMatchesAreHighlighted(true /* highlight */);
 273 m_activeMatchCount += matchCount;
 274 }
 275
 276 if (timeout)
 277 scopeStringMatchesSoon(scopingFrame, text, false /* reset */);
 278 else {
 279 // Scoping is done for this frame.
 280 Frame* nextFrame = DOMSupport::incrementFrame(scopingFrame, true /* forward */, false /* wrapFlag */);
 281 if (!nextFrame) {
 282 m_scopingComplete = true;
 283 return; // Scoping is done for all frames;
 284 }
 285 scopeStringMatchesSoon(nextFrame, text, false /* reset */);
 286 }
 287}
 288
 289void InPageSearchManager::scopeStringMatchesSoon(Frame* scopingFrame, const String& text, bool reset)
 290{
 291 m_deferredScopingWork.append(new DeferredScopeStringMatches(this, scopingFrame, text, reset));
 292}
 293
 294void InPageSearchManager::callScopeStringMatches(DeferredScopeStringMatches* caller, Frame* scopingFrame, const String& text, bool reset)
 295{
 296 m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
 297 scopeStringMatches(text, reset, scopingFrame);
 298 delete caller;
 299}
 300
 301void InPageSearchManager::cancelPendingScopingEffort()
 302{
 303 deleteAllValues(m_deferredScopingWork);
 304 m_deferredScopingWork.clear();
 305}
 306
174307}
175308}

Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.h

@@public:
4343 void frameUnloaded(const WebCore::Frame*);
4444
4545private:
 46 class DeferredScopeStringMatches;
 47 friend class DeferredScopeStringMatches;
 48
4649 void clearTextMatches();
4750 void setMarkerActive(WebCore::Range*, bool);
48  bool findAndMarkText(const String&, WebCore::Range*, WebCore::Frame*, const WebCore::FindOptions&);
 51 bool findAndMarkText(const String&, WebCore::Range*, WebCore::Frame*, const WebCore::FindOptions&, bool);
4952 bool shouldSearchForText(const String&);
 53 void scopeStringMatches(const String& text, bool reset, WebCore::Frame* scopingFrame = 0);
 54 void scopeStringMatchesSoon(WebCore::Frame* scopingFrame, const String& text, bool reset);
 55 void callScopeStringMatches(DeferredScopeStringMatches* caller, WebCore::Frame* scopingFrame, const String& text, bool reset);
 56 void cancelPendingScopingEffort();
5057
 58 Vector<DeferredScopeStringMatches*> m_deferredScopingWork;
5159 WebPagePrivate* m_webPage;
5260 RefPtr<WebCore::Range> m_activeMatch;
 61 RefPtr<WebCore::Range> m_resumeScopingFromRange;
5362 String m_activeSearchString;
5463 int m_activeMatchCount;
 64 bool m_scopingComplete;
 65 bool m_locatingActiveMatch;
 66 int m_activeMatchIndex;
5567};
5668
5769}