1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "nsComponentManagerUtils.h"
7 #include "nsCycleCollectionParticipant.h"
8 #include "nsISelectionController.h"
9 #include "nsIController.h"
10 #include "nsIControllers.h"
11 #include "nsIObserver.h"
12 #include "nsUnicharUtils.h"
13 #include "nsIFind.h"
14 #include "nsIWebBrowserFind.h"
15 #include "nsWeakReference.h"
16 #include "nsISelection.h"
17 #include "nsIDOMRange.h"
18 #include "nsIDocShellTreeItem.h"
19 #include "nsITypeAheadFind.h"
20 #include "nsISound.h"
21 
22 class nsPIDOMWindowInner;
23 class nsIPresShell;
24 class nsPresContext;
25 class nsRange;
26 
27 #define TYPEAHEADFIND_NOTFOUND_WAV_URL "chrome://global/content/notfound.wav"
28 
29 class nsTypeAheadFind : public nsITypeAheadFind,
30                         public nsIObserver,
31                         public nsSupportsWeakReference {
32  public:
33   nsTypeAheadFind();
34 
35   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
36   NS_DECL_NSITYPEAHEADFIND
37   NS_DECL_NSIOBSERVER
38 
39   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTypeAheadFind, nsITypeAheadFind)
40 
41  protected:
42   virtual ~nsTypeAheadFind();
43 
44   nsresult PrefsReset();
45 
46   void SaveFind();
47   void PlayNotFoundSound();
48   nsresult GetWebBrowserFind(nsIDocShell *aDocShell,
49                              nsIWebBrowserFind **aWebBrowserFind);
50 
51   void RangeStartsInsideLink(nsRange *aRange, nsIPresShell *aPresShell,
52                              bool *aIsInsideLink, bool *aIsStartingLink);
53 
54   void GetSelection(nsIPresShell *aPresShell, nsISelectionController **aSelCon,
55                     nsISelection **aDomSel);
56   // *aNewRange may not be collapsed.  If you want to collapse it in a
57   // particular way, you need to do it yourself.
58   bool IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext,
59                       nsIDOMRange *aRange, bool aMustBeVisible,
60                       bool aGetTopVisibleLeaf, nsIDOMRange **aNewRange,
61                       bool *aUsesIndependentSelection);
62   bool IsRangeRendered(nsIPresShell *aPresShell, nsPresContext *aPresContext,
63                        nsIDOMRange *aRange);
64   nsresult FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly,
65                      bool aIsFirstVisiblePreferred, bool aFindPrev,
66                      uint16_t *aResult);
67   nsresult GetSearchContainers(nsISupports *aContainer,
68                                nsISelectionController *aSelectionController,
69                                bool aIsFirstVisiblePreferred, bool aFindPrev,
70                                nsIPresShell **aPresShell,
71                                nsPresContext **aPresContext);
72 
73   // Get the pres shell from mPresShell and return it only if it is still
74   // attached to the DOM window.
75   already_AddRefed<nsIPresShell> GetPresShell();
76 
77   void ReleaseStrongMemberVariables();
78 
79   // Current find state
80   nsString mTypeAheadBuffer;
81   nsCString mNotFoundSoundURL;
82 
83   // PRBools are used instead of PRPackedBools because the address of the
84   // boolean variable is getting passed into a method.
85   bool mStartLinksOnlyPref;
86   bool mCaretBrowsingOn;
87   bool mDidAddObservers;
88   nsCOMPtr<nsIDOMElement> mFoundLink;  // Most recent elem found, if a link
89   nsCOMPtr<nsIDOMElement>
90       mFoundEditable;                 // Most recent elem found, if editable
91   nsCOMPtr<nsIDOMRange> mFoundRange;  // Most recent range found
92   nsCOMPtr<nsPIDOMWindowInner> mCurrentWindow;
93   // mLastFindLength is the character length of the last find string.  It is
94   // used for disabling the "not found" sound when using backspace or delete
95   uint32_t mLastFindLength;
96 
97   // Sound is played asynchronously on some platforms.
98   // If we destroy mSoundInterface before sound has played, it won't play
99   nsCOMPtr<nsISound> mSoundInterface;
100   bool mIsSoundInitialized;
101 
102   // where selection was when user started the find
103   nsCOMPtr<nsIDOMRange> mStartFindRange;
104   nsCOMPtr<nsIDOMRange> mSearchRange;
105   nsCOMPtr<nsIDOMRange> mStartPointRange;
106   nsCOMPtr<nsIDOMRange> mEndPointRange;
107 
108   // Cached useful interfaces
109   nsCOMPtr<nsIFind> mFind;
110 
111   bool mCaseSensitive;
112   bool mEntireWord;
113 
EnsureFind()114   bool EnsureFind() {
115     if (mFind) {
116       return true;
117     }
118 
119     mFind = do_CreateInstance("@mozilla.org/embedcomp/rangefind;1");
120     if (!mFind) {
121       return false;
122     }
123 
124     mFind->SetCaseSensitive(mCaseSensitive);
125     mFind->SetEntireWord(mEntireWord);
126 
127     return true;
128   }
129 
130   nsCOMPtr<nsIWebBrowserFind> mWebBrowserFind;
131 
132   // The focused content window that we're listening to and its cached objects
133   nsWeakPtr mDocShell;
134   nsWeakPtr mPresShell;
135   nsWeakPtr mSelectionController;
136   // Most recent match's controller
137 };
138