already_AddRefed<nsIContent> APZEventState::GetTouchRollup() const { nsCOMPtr<nsIContent> result = do_QueryReferent(mTouchRollup); return result.forget(); }
NS_IMETHODIMP nsPluginByteRangeStreamListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { nsresult rv; nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer); if (!finalStreamListener) return NS_ERROR_FAILURE; nsPluginStreamListenerPeer *pslp = static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get()); NS_ASSERTION(pslp->mRequests.IndexOfObject(GetBaseRequest(request)) != -1, "Untracked byte-range request?"); nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = serv->AsyncConvertData(MULTIPART_BYTERANGES, "*/*", finalStreamListener, nullptr, getter_AddRefs(mStreamConverter)); if (NS_SUCCEEDED(rv)) { rv = mStreamConverter->OnStartRequest(request, ctxt); if (NS_SUCCEEDED(rv)) return rv; } } mStreamConverter = 0; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request)); if (!httpChannel) { return NS_ERROR_FAILURE; } uint32_t responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { return NS_ERROR_FAILURE; } if (responseCode != 200) { uint32_t wantsAllNetworkStreams = 0; rv = pslp->GetPluginInstance()->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, &wantsAllNetworkStreams); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { wantsAllNetworkStreams = 0; } if (!wantsAllNetworkStreams) { return NS_ERROR_FAILURE; } } // if server cannot continue with byte range (206 status) and sending us whole object (200 status) // reset this seekable stream & try serve it to plugin instance as a file mStreamConverter = finalStreamListener; mRemoveMagicNumber = true; rv = pslp->ServeStreamAsFile(request, ctxt); return rv; }
already_AddRefed<nsIWidget> APZEventState::GetWidget() const { nsCOMPtr<nsIWidget> result = do_QueryReferent(mWidget); return result.forget(); }
nsresult DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, nsIDocument** aDocument, nsIDOMDocument** aDOMDocument) { *aDocument = nullptr; *aDOMDocument = nullptr; NS_ENSURE_STATE(mOwner); nsCOMPtr<nsIDOMDocumentType> doctype; // Indicate that there is no internal subset (not just an empty one) nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype), mOwner->NodeInfoManager(), nsGkAtoms::html, // aName EmptyString(), // aPublicId EmptyString(), // aSystemId NullString()); // aInternalSubset NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIGlobalObject> scriptHandlingObject = do_QueryReferent(mScriptObject); NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); nsCOMPtr<nsIDOMDocument> document; rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(), EmptyString(), doctype, mDocumentURI, mBaseURI, mOwner->NodePrincipal(), true, scriptHandlingObject, DocumentFlavorLegacyGuess); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocument> doc = do_QueryInterface(document); nsCOMPtr<Element> root = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr, kNameSpaceID_XHTML); rv = doc->AppendChildTo(root, false); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<Element> head = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr, kNameSpaceID_XHTML); rv = root->AppendChildTo(head, false); NS_ENSURE_SUCCESS(rv, rv); if (!DOMStringIsNull(aTitle)) { nsCOMPtr<Element> title = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr, kNameSpaceID_XHTML); rv = head->AppendChildTo(title, false); NS_ENSURE_SUCCESS(rv, rv); RefPtr<nsTextNode> titleText = new nsTextNode(doc->NodeInfoManager()); rv = titleText->SetText(aTitle, false); NS_ENSURE_SUCCESS(rv, rv); rv = title->AppendChildTo(titleText, false); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr<Element> body = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML); rv = root->AppendChildTo(body, false); NS_ENSURE_SUCCESS(rv, rv); // When the createHTMLDocument method is invoked, // use the registry of the associated document to the new instance. doc->UseRegistryFromDocument(mOwner); doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); doc.forget(aDocument); document.forget(aDOMDocument); return NS_OK; }
nsresult nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) { nsAutoCString rangeString; int32_t numRequests; MakeByteRangeString(rangeList, rangeString, &numRequests); if (numRequests == 0) return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsRefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner(); nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDocument> doc; if (owner) { rv = owner->GetDOMElement(getter_AddRefs(element)); NS_ENSURE_SUCCESS(rv, rv); rv = owner->GetDocument(getter_AddRefs(doc)); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks); nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup); nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsINode> requestingNode(do_QueryInterface(element)); if (requestingNode) { rv = NS_NewChannel(getter_AddRefs(channel), mURL, requestingNode, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, loadGroup, callbacks); } else { // in this else branch we really don't know where the load is coming // from and in fact should use something better than just using // a nullPrincipal as the loadingPrincipal. nsCOMPtr<nsIPrincipal> principal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv); NS_ENSURE_SUCCESS(rv, rv); rv = NS_NewChannel(getter_AddRefs(channel), mURL, principal, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, loadGroup, callbacks); } if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (!httpChannel) return NS_ERROR_FAILURE; httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false); mAbort = true; // instruct old stream listener to cancel // the request on the next ODA. nsCOMPtr<nsIStreamListener> converter; if (numRequests == 1) { converter = this; // set current stream offset equal to the first offset in the range list // it will work for single byte range request // for multy range we'll reset it in ODA SetStreamOffset(rangeList->offset); } else { nsWeakPtr weakpeer = do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this)); nsPluginByteRangeStreamListener *brrListener = new nsPluginByteRangeStreamListener(weakpeer); if (brrListener) converter = brrListener; else return NS_ERROR_OUT_OF_MEMORY; } mPendingRequests += numRequests; nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; rv = container->SetData(MAGIC_REQUEST_CONTEXT); if (NS_FAILED(rv)) return rv; rv = channel->AsyncOpen(converter, container); if (NS_SUCCEEDED(rv)) TrackRequest(channel); return rv; }
nsresult nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly, bool aIsFirstVisiblePreferred, bool aFindPrev, PRUint16* aResult) { *aResult = FIND_NOTFOUND; mFoundLink = nsnull; mFoundEditable = nsnull; mCurrentWindow = nsnull; nsCOMPtr<nsIPresShell> startingPresShell (GetPresShell()); if (!startingPresShell) { nsCOMPtr<nsIDocShell> ds = do_QueryReferent(mDocShell); NS_ENSURE_TRUE(ds, NS_ERROR_FAILURE); ds->GetPresShell(getter_AddRefs(startingPresShell)); mPresShell = do_GetWeakReference(startingPresShell); } nsCOMPtr<nsIPresShell> presShell(aPresShell); if (!presShell) { presShell = startingPresShell; // this is the current document if (!presShell) return NS_ERROR_FAILURE; } nsRefPtr<nsPresContext> presContext = presShell->GetPresContext(); if (!presContext) return NS_ERROR_FAILURE; nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelectionController> selectionController = do_QueryReferent(mSelectionController); if (!selectionController) { GetSelection(presShell, getter_AddRefs(selectionController), getter_AddRefs(selection)); // cache for reuse mSelectionController = do_GetWeakReference(selectionController); } else { selectionController->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); } nsCOMPtr<nsISupports> startingContainer = presContext->GetContainer(); nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(startingContainer)); NS_ASSERTION(treeItem, "Bug 175321 Crashes with Type Ahead Find [@ nsTypeAheadFind::FindItNow]"); if (!treeItem) return NS_ERROR_FAILURE; nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem; nsCOMPtr<nsIDocShell> currentDocShell; nsCOMPtr<nsIDocShell> startingDocShell(do_QueryInterface(startingContainer)); treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem)); nsCOMPtr<nsIDocShell> rootContentDocShell = do_QueryInterface(rootContentTreeItem); if (!rootContentDocShell) return NS_ERROR_FAILURE; nsCOMPtr<nsISimpleEnumerator> docShellEnumerator; rootContentDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent, nsIDocShell::ENUMERATE_FORWARDS, getter_AddRefs(docShellEnumerator)); // Default: can start at the current document nsCOMPtr<nsISupports> currentContainer = startingContainer = do_QueryInterface(rootContentDocShell); // Iterate up to current shell, if there's more than 1 that we're // dealing with bool hasMoreDocShells; while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) && hasMoreDocShells) { docShellEnumerator->GetNext(getter_AddRefs(currentContainer)); currentDocShell = do_QueryInterface(currentContainer); if (!currentDocShell || currentDocShell == startingDocShell || aIsFirstVisiblePreferred) break; } // ------------ Get ranges ready ---------------- nsCOMPtr<nsIDOMRange> returnRange; nsCOMPtr<nsIPresShell> focusedPS; if (NS_FAILED(GetSearchContainers(currentContainer, (!aIsFirstVisiblePreferred || mStartFindRange) ? selectionController.get() : nsnull, aIsFirstVisiblePreferred, aFindPrev, getter_AddRefs(presShell), getter_AddRefs(presContext)))) { return NS_ERROR_FAILURE; } PRInt16 rangeCompareResult = 0; mStartPointRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, mSearchRange, &rangeCompareResult); // No need to wrap find in doc if starting at beginning bool hasWrapped = (rangeCompareResult < 0); if (mTypeAheadBuffer.IsEmpty()) return NS_ERROR_FAILURE; mFind->SetFindBackwards(aFindPrev); while (PR_TRUE) { // ----- Outer while loop: go through all docs ----- while (PR_TRUE) { // === Inner while loop: go through a single doc === mFind->Find(mTypeAheadBuffer.get(), mSearchRange, mStartPointRange, mEndPointRange, getter_AddRefs(returnRange)); if (!returnRange) break; // Nothing found in this doc, go to outer loop (try next doc) // ------- Test resulting found range for success conditions ------ bool isInsideLink = false, isStartingLink = false; if (aIsLinksOnly) { // Don't check if inside link when searching all text RangeStartsInsideLink(returnRange, presShell, &isInsideLink, &isStartingLink); } bool usesIndependentSelection; if (!IsRangeVisible(presShell, presContext, returnRange, aIsFirstVisiblePreferred, PR_FALSE, getter_AddRefs(mStartPointRange), &usesIndependentSelection) || (aIsLinksOnly && !isInsideLink) || (mStartLinksOnlyPref && aIsLinksOnly && !isStartingLink)) { // ------ Failure ------ // Start find again from here returnRange->CloneRange(getter_AddRefs(mStartPointRange)); // Collapse to end mStartPointRange->Collapse(aFindPrev); continue; } // ------ Success! ------- // Hide old selection (new one may be on a different controller) if (selection) { selection->CollapseToStart(); SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ON); } // Make sure new document is selected if (presShell != startingPresShell) { // We are in a new document (because of frames/iframes) mPresShell = do_GetWeakReference(presShell); } nsCOMPtr<nsIDocument> document = do_QueryInterface(presShell->GetDocument()); NS_ASSERTION(document, "Wow, presShell doesn't have document!"); if (!document) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsPIDOMWindow> window = document->GetWindow(); NS_ASSERTION(window, "document has no window"); if (!window) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); if (usesIndependentSelection) { /* If a search result is found inside an editable element, we'll focus * the element only if focus is in our content window, i.e. * |if (focusedWindow.top == ourWindow.top)| */ bool shouldFocusEditableElement = false; if (fm) { nsCOMPtr<nsIDOMWindow> focusedWindow; nsresult rv = fm->GetFocusedWindow(getter_AddRefs(focusedWindow)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsPIDOMWindow> fwPI(do_QueryInterface(focusedWindow, &rv)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIDocShellTreeItem> fwTreeItem (do_QueryInterface(fwPI->GetDocShell(), &rv)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIDocShellTreeItem> fwRootTreeItem; rv = fwTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(fwRootTreeItem)); if (NS_SUCCEEDED(rv) && fwRootTreeItem == rootContentTreeItem) shouldFocusEditableElement = PR_TRUE; } } } } // We may be inside an editable element, and therefore the selection // may be controlled by a different selection controller. Walk up the // chain of parent nodes to see if we find one. nsCOMPtr<nsIDOMNode> node; returnRange->GetStartContainer(getter_AddRefs(node)); while (node) { nsCOMPtr<nsIDOMNSEditableElement> editable = do_QueryInterface(node); if (editable) { // Inside an editable element. Get the correct selection // controller and selection. nsCOMPtr<nsIEditor> editor; editable->GetEditor(getter_AddRefs(editor)); NS_ASSERTION(editor, "Editable element has no editor!"); if (!editor) { break; } editor->GetSelectionController( getter_AddRefs(selectionController)); if (selectionController) { selectionController->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); } mFoundEditable = do_QueryInterface(node); if (!shouldFocusEditableElement) break; // Otherwise move focus/caret to editable element if (fm) fm->SetFocus(mFoundEditable, 0); break; } nsIDOMNode* tmp = node; tmp->GetParentNode(getter_AddRefs(node)); } // If we reach here without setting mFoundEditable, then something // besides editable elements can cause us to have an independent // selection controller. I don't know whether this is possible. // Currently, we simply fall back to grabbing the document's selection // controller in this case. Perhaps we should reject this find match // and search again. NS_ASSERTION(mFoundEditable, "Independent selection controller on " "non-editable element!"); } if (!mFoundEditable) { // Not using a separate selection controller, so just get the // document's controller and selection. GetSelection(presShell, getter_AddRefs(selectionController), getter_AddRefs(selection)); } mSelectionController = do_GetWeakReference(selectionController); // Select the found text if (selection) { selection->RemoveAllRanges(); selection->AddRange(returnRange); } if (!mFoundEditable && fm) { nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(window); fm->MoveFocus(win, nsnull, nsIFocusManager::MOVEFOCUS_CARET, nsIFocusManager::FLAG_NOSCROLL | nsIFocusManager::FLAG_NOSWITCHFRAME, getter_AddRefs(mFoundLink)); } // Change selection color to ATTENTION and scroll to it. Careful: we // must wait until after we goof with focus above before changing to // ATTENTION, or when we MoveFocus() and the selection is not on a // link, we'll blur, which will lose the ATTENTION. if (selectionController) { // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ATTENTION); selectionController->ScrollSelectionIntoView( nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_WHOLE_SELECTION, nsISelectionController::SCROLL_SYNCHRONOUS); } mCurrentWindow = window; *aResult = hasWrapped ? FIND_WRAPPED : FIND_FOUND; return NS_OK; } // ======= end-inner-while (go through a single document) ========== // ---------- Nothing found yet, try next document ------------- bool hasTriedFirstDoc = false; do { // ==== Second inner loop - get another while ==== if (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) && hasMoreDocShells) { docShellEnumerator->GetNext(getter_AddRefs(currentContainer)); NS_ASSERTION(currentContainer, "HasMoreElements lied to us!"); currentDocShell = do_QueryInterface(currentContainer); if (currentDocShell) break; } else if (hasTriedFirstDoc) // Avoid potential infinite loop return NS_ERROR_FAILURE; // No content doc shells // Reached last doc shell, loop around back to first doc shell rootContentDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent, nsIDocShell::ENUMERATE_FORWARDS, getter_AddRefs(docShellEnumerator)); hasTriedFirstDoc = PR_TRUE; } while (docShellEnumerator); // ==== end second inner while === bool continueLoop = false; if (currentDocShell != startingDocShell) continueLoop = PR_TRUE; // Try next document else if (!hasWrapped || aIsFirstVisiblePreferred) { // Finished searching through docshells: // If aFirstVisiblePreferred == PR_TRUE, we may need to go through all // docshells twice -once to look for visible matches, the second time // for any match aIsFirstVisiblePreferred = PR_FALSE; hasWrapped = PR_TRUE; continueLoop = PR_TRUE; // Go through all docs again } if (continueLoop) { if (NS_FAILED(GetSearchContainers(currentContainer, nsnull, aIsFirstVisiblePreferred, aFindPrev, getter_AddRefs(presShell), getter_AddRefs(presContext)))) { continue; } if (aFindPrev) { // Reverse mode: swap start and end points, so that we start // at end of document and go to beginning nsCOMPtr<nsIDOMRange> tempRange; mStartPointRange->CloneRange(getter_AddRefs(tempRange)); mStartPointRange = mEndPointRange; mEndPointRange = tempRange; } continue; } // ------------- Failed -------------- break; } // end-outer-while: go through all docs return NS_ERROR_FAILURE; }
/* void notify(in nsITimer timer); */ NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) { // Note that as long as the image is animated, it will not be discarded, // so this should never happen... nsresult rv = RestoreDiscardedData(); NS_ENSURE_SUCCESS(rv, rv); // This should never happen since the timer is only set up in StartAnimation() // after mAnim is checked to exist. NS_ENSURE_TRUE(mAnim, NS_ERROR_UNEXPECTED); NS_ASSERTION(mAnim->timer == timer, "imgContainer::Notify() called with incorrect timer"); if (!mAnim->animating || !mAnim->timer) return NS_OK; nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver)); if (!observer) { // the imgRequest that owns us is dead, we should die now too. StopAnimation(); return NS_OK; } if (mNumFrames == 0) return NS_OK; gfxIImageFrame *nextFrame = nsnull; PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex; PRInt32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1; PRInt32 timeout = 0; // If we're done decoding the next frame, go ahead and display it now and // reinit the timer with the next frame's delay time. // currentDecodingFrameIndex is not set until the second frame has // finished decoding (see EndFrameDecode) if (mAnim->doneDecoding || (nextFrameIndex < mAnim->currentDecodingFrameIndex)) { if (mNumFrames == nextFrameIndex) { // End of Animation // If animation mode is "loop once", it's time to stop animating if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) { StopAnimation(); return NS_OK; } else { // We may have used compositingFrame to build a frame, and then copied // it back into mFrames[..]. If so, delete composite to save memory if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1) mAnim->compositingFrame = nsnull; } nextFrameIndex = 0; if (mLoopCount > 0) mLoopCount--; } if (!(nextFrame = mFrames[nextFrameIndex])) { // something wrong with the next frame, skip it mAnim->currentAnimationFrameIndex = nextFrameIndex; mAnim->timer->SetDelay(100); return NS_OK; } nextFrame->GetTimeout(&timeout); } else if (nextFrameIndex == mAnim->currentDecodingFrameIndex) { // Uh oh, the frame we want to show is currently being decoded (partial) // Wait a bit and try again mAnim->timer->SetDelay(100); return NS_OK; } else { // (nextFrameIndex > currentDecodingFrameIndex) // We shouldn't get here. However, if we are requesting a frame // that hasn't been decoded yet, go back to the last frame decoded NS_WARNING("imgContainer::Notify() Frame is passed decoded frame"); nextFrameIndex = mAnim->currentDecodingFrameIndex; if (!(nextFrame = mFrames[nextFrameIndex])) { // something wrong with the next frame, skip it mAnim->currentAnimationFrameIndex = nextFrameIndex; mAnim->timer->SetDelay(100); return NS_OK; } nextFrame->GetTimeout(&timeout); } if (timeout > 0) mAnim->timer->SetDelay(timeout); else StopAnimation(); nsIntRect dirtyRect; gfxIImageFrame *frameToUse = nsnull; if (nextFrameIndex == 0) { frameToUse = nextFrame; dirtyRect = mAnim->firstFrameRefreshArea; } else { gfxIImageFrame *prevFrame = mFrames[previousFrameIndex]; if (!prevFrame) return NS_OK; // Change frame and announce it if (NS_FAILED(DoComposite(&frameToUse, &dirtyRect, prevFrame, nextFrame, nextFrameIndex))) { // something went wrong, move on to next NS_WARNING("imgContainer::Notify(): Composing Frame Failed\n"); mAnim->currentAnimationFrameIndex = nextFrameIndex; return NS_OK; } } // Set currentAnimationFrameIndex at the last possible moment mAnim->currentAnimationFrameIndex = nextFrameIndex; // Refreshes the screen observer->FrameChanged(this, frameToUse, &dirtyRect); return NS_OK; }
//----------------------------------------------------------------------------- nsISelection* nsCaret::GetCaretDOMSelection() { nsCOMPtr<nsISelection> sel(do_QueryReferent(mDomSelectionWeak)); return sel; }
nsresult nsCaret::GetCaretFrameForNodeOffset(nsIContent* aContentNode, PRInt32 aOffset, nsFrameSelection::HINT aFrameHint, PRUint8 aBidiLevel, nsIFrame** aReturnFrame, PRInt32* aReturnOffset) { //get frame selection and find out what frame to use... nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell); if (!presShell) return NS_ERROR_FAILURE; nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection(); if (!frameSelection) return NS_ERROR_FAILURE; nsIFrame* theFrame = nsnull; PRInt32 theFrameOffset = 0; theFrame = frameSelection->GetFrameForNodeOffset(aContentNode, aOffset, aFrameHint, &theFrameOffset); if (!theFrame) return NS_ERROR_FAILURE; // if theFrame is after a text frame that's logically at the end of the line // (e.g. if theFrame is a <br> frame), then put the caret at the end of // that text frame instead. This way, the caret will be positioned as if // trailing whitespace was not trimmed. AdjustCaretFrameForLineEnd(&theFrame, &theFrameOffset); // Mamdouh : modification of the caret to work at rtl and ltr with Bidi // // Direction Style from this->GetStyleData() // now in (visibility->mDirection) // ------------------ // NS_STYLE_DIRECTION_LTR : LTR or Default // NS_STYLE_DIRECTION_RTL // NS_STYLE_DIRECTION_INHERIT if (mBidiUI) { // If there has been a reflow, take the caret Bidi level to be the level of the current frame if (aBidiLevel & BIDI_LEVEL_UNDEFINED) aBidiLevel = NS_GET_EMBEDDING_LEVEL(theFrame); PRInt32 start; PRInt32 end; nsIFrame* frameBefore; nsIFrame* frameAfter; PRUint8 levelBefore; // Bidi level of the character before the caret PRUint8 levelAfter; // Bidi level of the character after the caret theFrame->GetOffsets(start, end); if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset) { nsPrevNextBidiLevels levels = frameSelection-> GetPrevNextBidiLevels(aContentNode, aOffset, PR_FALSE); /* Boundary condition, we need to know the Bidi levels of the characters before and after the caret */ if (levels.mFrameBefore || levels.mFrameAfter) { frameBefore = levels.mFrameBefore; frameAfter = levels.mFrameAfter; levelBefore = levels.mLevelBefore; levelAfter = levels.mLevelAfter; if ((levelBefore != levelAfter) || (aBidiLevel != levelBefore)) { aBidiLevel = NS_MAX(aBidiLevel, NS_MIN(levelBefore, levelAfter)); // rule c3 aBidiLevel = NS_MIN(aBidiLevel, NS_MAX(levelBefore, levelAfter)); // rule c4 if (aBidiLevel == levelBefore // rule c1 || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelBefore) & 1)) // rule c5 || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelBefore) & 1))) // rule c9 { if (theFrame != frameBefore) { if (frameBefore) // if there is a frameBefore, move into it { theFrame = frameBefore; theFrame->GetOffsets(start, end); theFrameOffset = end; } else { // if there is no frameBefore, we must be at the beginning of the line // so we stay with the current frame. // Exception: when the first frame on the line has a different Bidi level from the paragraph level, there is no // real frame for the caret to be in. We have to find the visually first frame on the line. PRUint8 baseLevel = NS_GET_BASE_LEVEL(frameAfter); if (baseLevel != levelAfter) { nsPeekOffsetStruct pos; pos.SetData(eSelectBeginLine, eDirPrevious, 0, 0, PR_FALSE, PR_TRUE, PR_FALSE, PR_TRUE); if (NS_SUCCEEDED(frameAfter->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; } } } } } else if (aBidiLevel == levelAfter // rule c2 || (aBidiLevel > levelBefore && aBidiLevel < levelAfter && !((aBidiLevel ^ levelAfter) & 1)) // rule c6 || (aBidiLevel < levelBefore && aBidiLevel > levelAfter && !((aBidiLevel ^ levelAfter) & 1))) // rule c10 { if (theFrame != frameAfter) { if (frameAfter) { // if there is a frameAfter, move into it theFrame = frameAfter; theFrame->GetOffsets(start, end); theFrameOffset = start; } else { // if there is no frameAfter, we must be at the end of the line // so we stay with the current frame. // Exception: when the last frame on the line has a different Bidi level from the paragraph level, there is no // real frame for the caret to be in. We have to find the visually last frame on the line. PRUint8 baseLevel = NS_GET_BASE_LEVEL(frameBefore); if (baseLevel != levelBefore) { nsPeekOffsetStruct pos; pos.SetData(eSelectEndLine, eDirNext, 0, 0, PR_FALSE, PR_TRUE, PR_FALSE, PR_TRUE); if (NS_SUCCEEDED(frameBefore->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; } } } } } else if (aBidiLevel > levelBefore && aBidiLevel < levelAfter // rule c7/8 && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity { if (NS_SUCCEEDED(frameSelection->GetFrameFromLevel(frameAfter, eDirNext, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelAfter = NS_GET_EMBEDDING_LEVEL(theFrame); if (aBidiLevel & 1) // c8: caret to the right of the rightmost character theFrameOffset = (levelAfter & 1) ? start : end; else // c7: caret to the left of the leftmost character theFrameOffset = (levelAfter & 1) ? end : start; } } else if (aBidiLevel < levelBefore && aBidiLevel > levelAfter // rule c11/12 && !((levelBefore ^ levelAfter) & 1) // before and after have the same parity && ((aBidiLevel ^ levelAfter) & 1)) // caret has different parity { if (NS_SUCCEEDED(frameSelection->GetFrameFromLevel(frameBefore, eDirPrevious, aBidiLevel, &theFrame))) { theFrame->GetOffsets(start, end); levelBefore = NS_GET_EMBEDDING_LEVEL(theFrame); if (aBidiLevel & 1) // c12: caret to the left of the leftmost character theFrameOffset = (levelBefore & 1) ? end : start; else // c11: caret to the right of the rightmost character theFrameOffset = (levelBefore & 1) ? start : end; } } } } } } *aReturnFrame = theFrame; *aReturnOffset = theFrameOffset; return NS_OK; }
void nsCaret::DrawCaret(PRBool aInvalidate) { // Do we need to draw the caret at all? if (!MustDrawCaret(PR_FALSE)) return; // Can we draw the caret now? nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell); NS_ENSURE_TRUE(presShell, /**/); { PRBool isPaintingSuppressed; presShell->IsPaintingSuppressed(&isPaintingSuppressed); if (isPaintingSuppressed) { if (!mDrawn) mPendingDraw = PR_TRUE; // PresShell::UnsuppressAndInvalidate() will call CheckCaretDrawingState() // to get us drawn. return; } } nsCOMPtr<nsIDOMNode> node; PRInt32 offset; nsFrameSelection::HINT hint; PRUint8 bidiLevel; if (!mDrawn) { nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak); nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection)); if (!privateSelection) return; PRBool isCollapsed = PR_FALSE; domSelection->GetIsCollapsed(&isCollapsed); if (!mShowDuringSelection && !isCollapsed) return; PRBool hintRight; privateSelection->GetInterlinePosition(&hintRight);//translate hint. hint = hintRight ? nsFrameSelection::HINTRIGHT : nsFrameSelection::HINTLEFT; // get the node and offset, which is where we want the caret to draw domSelection->GetFocusNode(getter_AddRefs(node)); if (!node) return; if (NS_FAILED(domSelection->GetFocusOffset(&offset))) return; nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection(); if (!frameSelection) return; bidiLevel = frameSelection->GetCaretBidiLevel(); mPendingDraw = PR_FALSE; } else { if (!mLastContent) { mDrawn = PR_FALSE; return; } if (!mLastContent->IsInDoc()) { mLastContent = nsnull; mDrawn = PR_FALSE; return; } node = do_QueryInterface(mLastContent); offset = mLastContentOffset; hint = mLastHint; bidiLevel = mLastBidiLevel; } DrawAtPositionWithHint(node, offset, hint, bidiLevel, aInvalidate); ToggleDrawnStatus(); }
nsresult nsCaret::UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset) { NS_ASSERTION(aFrame, "Should have a frame here"); nsRect frameRect = aFrame->GetRect(); frameRect.x = 0; frameRect.y = 0; nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell); if (!presShell) return NS_ERROR_FAILURE; // If we got a zero-height frame we should figure out a height. We have to do // this after we've got an RC. if (frameRect.height == 0) { nsCOMPtr<nsIFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); if (fm) { nscoord ascent, descent; fm->GetMaxAscent(ascent); fm->GetMaxDescent(descent); frameRect.height = ascent + descent; // Place the caret on the baseline for inline frames, except when there is // a frame on the line with non-zero height. XXXmats why the exception? -- // I don't know but it seems to be necessary, see bug 503531. if (aFrame->GetStyleDisplay()->IsInlineOutside() && !FramesOnSameLineHaveZeroHeight(aFrame)) frameRect.y -= ascent; } } mCaretRect = frameRect; nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak); nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection); nsPoint framePos; // if cache in selection is available, apply it, else refresh it nsresult rv = privateSelection->GetCachedFrameOffset(aFrame, aFrameOffset, framePos); if (NS_FAILED(rv)) { mCaretRect.Empty(); return rv; } mCaretRect += framePos; Metrics metrics = ComputeMetrics(aFrame, aFrameOffset, mCaretRect.height); mCaretRect.width = metrics.mCaretWidth; // Clamp our position to be within our scroll frame. If we don't, then it // clips us, and we don't appear at all. See bug 335560. nsIFrame *scrollFrame = nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::scrollFrame); if (scrollFrame) { // First, use the scrollFrame to get at the scrollable view that we're in. nsIScrollableFrame *sf = do_QueryFrame(scrollFrame); nsIFrame *scrolled = sf->GetScrolledFrame(); nsRect caretInScroll = mCaretRect + aFrame->GetOffsetTo(scrolled); // Now see if thet caret extends beyond the view's bounds. If it does, // then snap it back, put it as close to the edge as it can. nscoord overflow = caretInScroll.XMost() - scrolled->GetOverflowRectRelativeToSelf().width; if (overflow > 0) mCaretRect.x -= overflow; } // on RTL frames the right edge of mCaretRect must be equal to framePos const nsStyleVisibility* vis = aFrame->GetStyleVisibility(); if (NS_STYLE_DIRECTION_RTL == vis->mDirection) mCaretRect.x -= mCaretRect.width; return UpdateHookRect(presShell->GetPresContext(), metrics); }
nsINode* LoadInfo::LoadingNode() { nsCOMPtr<nsINode> node = do_QueryReferent(mLoadingContext); return node; }
already_AddRefed<nsIEditor> TextComposition::GetEditor() const { nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorWeak); return editor.forget(); }
NS_IMETHODIMP nsTypeAheadFind::Find(const nsAString& aSearchString, bool aLinksOnly, PRUint16* aResult) { *aResult = FIND_NOTFOUND; nsCOMPtr<nsIPresShell> presShell (GetPresShell()); if (!presShell) { nsCOMPtr<nsIDocShell> ds (do_QueryReferent(mDocShell)); NS_ENSURE_TRUE(ds, NS_ERROR_FAILURE); ds->GetPresShell(getter_AddRefs(presShell)); mPresShell = do_GetWeakReference(presShell); } nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelectionController> selectionController = do_QueryReferent(mSelectionController); if (!selectionController) { GetSelection(presShell, getter_AddRefs(selectionController), getter_AddRefs(selection)); // cache for reuse mSelectionController = do_GetWeakReference(selectionController); } else { selectionController->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); } if (selection) selection->CollapseToStart(); if (aSearchString.IsEmpty()) { mTypeAheadBuffer.Truncate(); // These will be initialized to their true values after the first character // is typed mStartFindRange = nsnull; mSelectionController = nsnull; *aResult = FIND_FOUND; return NS_OK; } bool atEnd = false; if (mTypeAheadBuffer.Length()) { const nsAString& oldStr = Substring(mTypeAheadBuffer, 0, mTypeAheadBuffer.Length()); const nsAString& newStr = Substring(aSearchString, 0, mTypeAheadBuffer.Length()); if (oldStr.Equals(newStr)) atEnd = PR_TRUE; const nsAString& newStr2 = Substring(aSearchString, 0, aSearchString.Length()); const nsAString& oldStr2 = Substring(mTypeAheadBuffer, 0, aSearchString.Length()); if (oldStr2.Equals(newStr2)) atEnd = PR_TRUE; if (!atEnd) mStartFindRange = nsnull; } if (!mIsSoundInitialized && !mNotFoundSoundURL.IsEmpty()) { // This makes sure system sound library is loaded so that // there's no lag before the first sound is played // by waiting for the first keystroke, we still get the startup time benefits. mIsSoundInitialized = PR_TRUE; mSoundInterface = do_CreateInstance("@mozilla.org/sound;1"); if (mSoundInterface && !mNotFoundSoundURL.Equals(NS_LITERAL_CSTRING("beep"))) { mSoundInterface->Init(); } } #ifdef XP_WIN // After each keystroke, ensure sound object is destroyed, to free up memory // allocated for error sound, otherwise Windows' nsISound impl // holds onto the last played sound, using up memory. mSoundInterface = nsnull; #endif PRInt32 bufferLength = mTypeAheadBuffer.Length(); mTypeAheadBuffer = aSearchString; bool isFirstVisiblePreferred = false; // --------- Initialize find if 1st char ---------- if (bufferLength == 0) { // If you can see the selection (not collapsed or thru caret browsing), // or if already focused on a page element, start there. // Otherwise we're going to start at the first visible element bool isSelectionCollapsed = true; if (selection) selection->GetIsCollapsed(&isSelectionCollapsed); // If true, we will scan from top left of visible area // If false, we will scan from start of selection isFirstVisiblePreferred = !atEnd && !mCaretBrowsingOn && isSelectionCollapsed; if (isFirstVisiblePreferred) { // Get the focused content. If there is a focused node, ensure the // selection is at that point. Otherwise, we will just want to start // from the caret position or the beginning of the document. nsPresContext* presContext = presShell->GetPresContext(); NS_ENSURE_TRUE(presContext, NS_OK); nsCOMPtr<nsIDocument> document = do_QueryInterface(presShell->GetDocument()); if (!document) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(document->GetWindow()); nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); if (fm) { nsCOMPtr<nsIDOMElement> focusedElement; nsCOMPtr<nsIDOMWindow> focusedWindow; fm->GetFocusedElementForWindow(window, PR_FALSE, getter_AddRefs(focusedWindow), getter_AddRefs(focusedElement)); // If the root element is focused, then it's actually the document // that has the focus, so ignore this. if (focusedElement && !SameCOMIdentity(focusedElement, document->GetRootElement())) { fm->MoveCaretToFocus(window); isFirstVisiblePreferred = PR_FALSE; } } } } // ----------- Find the text! --------------------- // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. nsresult rv = FindItNow(nsnull, aLinksOnly, isFirstVisiblePreferred, PR_FALSE, aResult); // ---------Handle success or failure --------------- if (NS_SUCCEEDED(rv)) { if (mTypeAheadBuffer.Length() == 1) { // If first letter, store where the first find succeeded // (mStartFindRange) mStartFindRange = nsnull; if (selection) { nsCOMPtr<nsIDOMRange> startFindRange; selection->GetRangeAt(0, getter_AddRefs(startFindRange)); if (startFindRange) startFindRange->CloneRange(getter_AddRefs(mStartFindRange)); } } } else { // Error sound if (mTypeAheadBuffer.Length() > mLastFindLength) PlayNotFoundSound(); } SaveFind(); return NS_OK; }
bool Equals(const nsDocLoader::nsListenerInfo& aInfo, nsIWebProgressListener* const& aListener) const { nsCOMPtr<nsIWebProgressListener> listener = do_QueryReferent(aInfo.mWeakListener); return aListener == listener; }
//----------------------------------------------------------------------------- void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsIView **outRenderingView, nsIView **outRelativeView) { if (!caretFrame || !outRenderingView) return; *outRenderingView = nsnull; if (outRelativeView) *outRelativeView = nsnull; NS_ASSERTION(caretFrame, "Should have a frame here"); viewOffset.x = 0; viewOffset.y = 0; nsPoint withinViewOffset(0, 0); // get the offset of this frame from its parent view (walks up frame hierarchy) nsIView* theView = nsnull; caretFrame->GetOffsetFromView(withinViewOffset, &theView); if (!theView) return; if (outRelativeView && coordType == eClosestViewCoordinates) *outRelativeView = theView; // Note: views are not refcounted. nsIView* returnView = nsIView::GetViewFor(theView->GetNearestWidget(nsnull)); // This gets uses the first view with a widget if (coordType == eRenderingViewCoordinates) { if (returnView) { // Now adjust the view offset for this view. withinViewOffset += theView->GetOffsetTo(returnView); // Account for the view's origin not lining up with the widget's // (bug 190290) withinViewOffset += returnView->GetPosition() - returnView->GetBounds().TopLeft(); viewOffset = withinViewOffset; if (outRelativeView) *outRelativeView = returnView; } } else { // window-relative coordinates. Done for us by the view. withinViewOffset += theView->GetOffsetTo(nsnull); viewOffset = withinViewOffset; // Get the relative view for top level window coordinates if (outRelativeView && coordType == eTopLevelWindowCoordinates) { nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell); if (presShell) { nsRootPresContext* rootPC = presShell->GetPresContext()->GetRootPresContext(); if (rootPC) { nsIViewManager* vm = rootPC->PresShell()->GetViewManager(); if (vm) { vm->GetRootView(*outRelativeView); } } } } } *outRenderingView = returnView; }
/* boolean findNext (); */ NS_IMETHODIMP nsWebBrowserFind::FindNext(bool *outDidFind) { NS_ENSURE_ARG_POINTER(outDidFind); *outDidFind = false; NS_ENSURE_TRUE(CanFindNext(), NS_ERROR_NOT_INITIALIZED); nsresult rv = NS_OK; nsCOMPtr<nsIDOMWindow> searchFrame = do_QueryReferent(mCurrentSearchFrame); NS_ENSURE_TRUE(searchFrame, NS_ERROR_NOT_INITIALIZED); nsCOMPtr<nsIDOMWindow> rootFrame = do_QueryReferent(mRootSearchFrame); NS_ENSURE_TRUE(rootFrame, NS_ERROR_NOT_INITIALIZED); // first, if there's a "cmd_findagain" observer around, check to see if it // wants to perform the find again command . If it performs the find again // it will return true, in which case we exit ::FindNext() early. // Otherwise, nsWebBrowserFind needs to perform the find again command itself // this is used by nsTypeAheadFind, which controls find again when it was // the last executed find in the current window. nsCOMPtr<nsIObserverService> observerSvc = mozilla::services::GetObserverService(); if (observerSvc) { nsCOMPtr<nsISupportsInterfacePointer> windowSupportsData = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsISupports> searchWindowSupports = do_QueryInterface(rootFrame); windowSupportsData->SetData(searchWindowSupports); NS_NAMED_LITERAL_STRING(dnStr, "down"); NS_NAMED_LITERAL_STRING(upStr, "up"); observerSvc->NotifyObservers(windowSupportsData, "nsWebBrowserFind_FindAgain", mFindBackwards? upStr.get(): dnStr.get()); windowSupportsData->GetData(getter_AddRefs(searchWindowSupports)); // findnext performed if search window data cleared out *outDidFind = searchWindowSupports == nsnull; if (*outDidFind) return NS_OK; } // next, look in the current frame. If found, return. // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. rv = SearchInFrame(searchFrame, false, outDidFind); if (NS_FAILED(rv)) return rv; if (*outDidFind) return OnFind(searchFrame); // we are done // if we are not searching other frames, return if (!mSearchSubFrames && !mSearchParentFrames) return NS_OK; nsIDocShell *rootDocShell = GetDocShellFromWindow(rootFrame); if (!rootDocShell) return NS_ERROR_FAILURE; PRInt32 enumDirection; if (mFindBackwards) enumDirection = nsIDocShell::ENUMERATE_BACKWARDS; else enumDirection = nsIDocShell::ENUMERATE_FORWARDS; nsCOMPtr<nsISimpleEnumerator> docShellEnumerator; rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll, enumDirection, getter_AddRefs(docShellEnumerator)); if (NS_FAILED(rv)) return rv; // remember where we started nsCOMPtr<nsIDocShellTreeItem> startingItem = do_QueryInterface(GetDocShellFromWindow(searchFrame), &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIDocShellTreeItem> curItem; // XXX We should avoid searching in frameset documents here. // We also need to honour mSearchSubFrames and mSearchParentFrames. bool hasMore, doFind = false; while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr<nsISupports> curSupports; rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports)); if (NS_FAILED(rv)) break; curItem = do_QueryInterface(curSupports, &rv); if (NS_FAILED(rv)) break; if (doFind) { searchFrame = do_GetInterface(curItem, &rv); if (NS_FAILED(rv)) break; OnStartSearchFrame(searchFrame); // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. rv = SearchInFrame(searchFrame, false, outDidFind); if (NS_FAILED(rv)) return rv; if (*outDidFind) return OnFind(searchFrame); // we are done OnEndSearchFrame(searchFrame); } if (curItem.get() == startingItem.get()) doFind = true; // start looking in frames after this one }; if (!mWrapFind) { // remember where we left off SetCurrentSearchFrame(searchFrame); return NS_OK; } // From here on, we're wrapping, first through the other frames, // then finally from the beginning of the starting frame back to // the starting point. // because nsISimpleEnumerator is totally lame and isn't resettable, I // have to make a new one docShellEnumerator = nsnull; rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll, enumDirection, getter_AddRefs(docShellEnumerator)); if (NS_FAILED(rv)) return rv; while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr<nsISupports> curSupports; rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports)); if (NS_FAILED(rv)) break; curItem = do_QueryInterface(curSupports, &rv); if (NS_FAILED(rv)) break; if (curItem.get() == startingItem.get()) { // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. rv = SearchInFrame(searchFrame, true, outDidFind); if (NS_FAILED(rv)) return rv; if (*outDidFind) return OnFind(searchFrame); // we are done break; } searchFrame = do_GetInterface(curItem, &rv); if (NS_FAILED(rv)) break; OnStartSearchFrame(searchFrame); // Beware! This may flush notifications via synchronous // ScrollSelectionIntoView. rv = SearchInFrame(searchFrame, false, outDidFind); if (NS_FAILED(rv)) return rv; if (*outDidFind) return OnFind(searchFrame); // we are done OnEndSearchFrame(searchFrame); } // remember where we left off SetCurrentSearchFrame(searchFrame); NS_ASSERTION(NS_SUCCEEDED(rv), "Something failed"); return rv; }
nsresult sbLocalDatabaseLibraryFactory::CreateLibraryFromDatabase(nsIFile* aDatabase, sbILibrary** _retval, nsIPropertyBag2* aCreationParameters, nsString aResourceGUID /* = EmptyString() */) { NS_ENSURE_ARG_POINTER(aDatabase); NS_ENSURE_ARG_POINTER(_retval); nsresult rv; // Get a unique value for this database file. nsCOMPtr<nsIHashable> hashable = do_QueryInterface(aDatabase, &rv); NS_ENSURE_SUCCESS(rv, rv); // We have to copy the file name escaping logic from when we actually create // the database, otherwise we end up re-initizliaing the database over and over. nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> databaseURI; rv = NS_NewFileURI(getter_AddRefs(databaseURI), aDatabase, ioService); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURL> databaseURL = do_QueryInterface(databaseURI, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString utf8GUID; rv = databaseURL->GetFileBaseName(utf8GUID); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> databaseParent; rv = aDatabase->GetParent(getter_AddRefs(databaseParent)); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString fileName; rv = databaseURL->GetFileName(fileName); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> escapedFile; rv = databaseParent->Clone(getter_AddRefs(escapedFile)); NS_ENSURE_SUCCESS(rv, rv); rv = escapedFile->Append(NS_ConvertUTF8toUTF16(fileName)); NS_ENSURE_SUCCESS(rv, rv); // On Windows, if the file does not exist, its hashcode is different from when it does. // If we ever attempt to get the hash code while it doesn't exist, the // nsLocalFile caches the hash code and stays incorrect. bool exists; rv = escapedFile->Exists(&exists); NS_ENSURE_SUCCESS(rv, rv); // See if we've already created this library. If we have (and it is still // alive) just return it. nsCOMPtr<nsIWeakReference> weakRef; if (exists && mCreatedLibraries.Get(hashable, getter_AddRefs(weakRef))) { nsCOMPtr<sbILibrary> existingLibrary = do_QueryReferent(weakRef, &rv); NS_ENSURE_SUCCESS(rv, rv); if (existingLibrary) { existingLibrary.swap(*_retval); return NS_OK; } mCreatedLibraries.Remove(hashable); } // If the database file does not exist, create and initalize it. Otherwise, // update it. if (!exists) { rv = InitalizeLibrary(aDatabase, aResourceGUID); NS_ENSURE_SUCCESS(rv, rv); } else { rv = UpdateLibrary(aDatabase); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr<nsIURI> databaseLocation; rv = NS_NewFileURI(getter_AddRefs(databaseLocation), databaseParent, ioService); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<sbLocalDatabaseLibrary> library(new sbLocalDatabaseLibrary()); NS_ENSURE_TRUE(library, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr<nsIPropertyBag2> creationParams = aCreationParameters; if (!creationParams) { nsCOMPtr<nsIWritablePropertyBag2> bag = do_CreateInstance(SB_PROPERTYBAG_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = bag->SetPropertyAsInterface(NS_LITERAL_STRING(PROPERTY_KEY_DATABASEFILE), aDatabase); NS_ENSURE_SUCCESS(rv, rv); creationParams = do_QueryInterface(bag, &rv); NS_ENSURE_SUCCESS(rv, rv); } rv = library->Init(NS_ConvertUTF8toUTF16(utf8GUID), creationParams, this, databaseLocation); NS_ENSURE_SUCCESS(rv, rv); // Add this library to our table of created libraries. weakRef = do_GetWeakReference(NS_ISUPPORTS_CAST(sbILibrary*, library), &rv); NS_ENSURE_SUCCESS(rv, rv); bool success = mCreatedLibraries.Put(hashable, weakRef); NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); NS_ADDREF(*_retval = library); return NS_OK; }