sbMacFileSystemWatcher.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2009 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include "sbMacFileSystemWatcher.h"
28 
29 #include <sbDebugUtils.h>
30 
36 //------------------------------------------------------------------------------
37 // FSEvents Callback
38 
39 /* static */ void
40 sbMacFileSystemWatcher::FSEventCallback(ConstFSEventStreamRef aStreamRef,
41  void *aClientCallbackInfo,
42  size_t aNumEvents,
43  const char *const aEventPaths[],
44  const FSEventStreamEventFlags aEventFlags[],
45  const FSEventStreamEventId aEventIds[])
46 {
47  TRACE("%s: %i events", __FUNCTION__, aNumEvents);
48  sbMacFileSystemWatcher *watcher =
49  static_cast<sbMacFileSystemWatcher *>(aClientCallbackInfo);
50  if (!watcher) {
51  return;
52  }
53 
54  sbStringArray paths;
55  for (unsigned int i = 0; i < aNumEvents; i++) {
56  nsString curPath;
57  curPath.AppendLiteral(aEventPaths[i]);
58  paths.AppendElement(curPath);
59  }
60 
61  watcher->OnFileSystemEvents(paths);
62 }
63 
64 //------------------------------------------------------------------------------
65 
67 {
68  SB_PRLOG_SETUP(sbMacFSWatcher);
69 
70  // Check to see if the current runtime is at least 10.5 or higher.
71  mIsSupported = PR_FALSE;
72  SInt32 macVersion;
73  if (Gestalt(gestaltSystemVersion, &macVersion) == noErr) {
74  if (macVersion >= 0x1050) {
75  mIsSupported = PR_TRUE;
76  }
77  }
78 }
79 
81 {
82 }
83 
84 NS_IMETHODIMP
86  const nsAString & aRootPath,
87  PRBool aIsRecursive)
88 {
89  TRACE("%s: path=%s", __FUNCTION__, NS_ConvertUTF16toUTF8(aRootPath).get());
90  if (!mIsSupported) {
91  return NS_ERROR_NOT_IMPLEMENTED;
92  }
93 
94  return sbBaseFileSystemWatcher::Init(aListener, aRootPath, aIsRecursive);
95 }
96 
97 NS_IMETHODIMP
98 sbMacFileSystemWatcher::InitWithSession(const nsACString & aSessionGuid,
99  sbIFileSystemListener *aListener)
100 {
101  TRACE("%s: session %s", __FUNCTION__, aSessionGuid.BeginReading());
102  if (!mIsSupported) {
103  return NS_ERROR_NOT_IMPLEMENTED;
104  }
105 
106  return sbBaseFileSystemWatcher::InitWithSession(aSessionGuid, aListener);
107 }
108 
109 NS_IMETHODIMP
110 sbMacFileSystemWatcher::StopWatching(PRBool aShouldSaveSession)
111 {
112  TRACE("%s: save %i", __FUNCTION__, aShouldSaveSession);
113  if (!mIsSupported) {
114  return NS_ERROR_NOT_IMPLEMENTED;
115  }
116 
117  if (!mIsWatching) {
118  return NS_OK;
119  }
120 
121  if (mContext) {
122  free(mContext);
123  }
124 
125  FSEventStreamStop(mStream);
126  FSEventStreamInvalidate(mStream);
127  FSEventStreamRelease(mStream);
128 
129  // The base class takes care of cleaning up the tree and notifying the
130  // listener.
131  return sbBaseFileSystemWatcher::StopWatching(aShouldSaveSession);
132 }
133 
134 void
136 {
137  PRUint32 length = aEventPaths.Length();
138  for (PRUint32 i = 0; i < length; i++) {
139  mTree->Update(aEventPaths[i]);
140  }
141 }
142 
143 //------------------------------------------------------------------------------
144 // sbFileSystemTreeListener
145 
146 NS_IMETHODIMP
147 sbMacFileSystemWatcher::OnTreeReady(const nsAString & aTreeRootPath,
148  sbStringArray & aDirPathArray)
149 {
150  TRACE("%s: tree at %s ready", __FUNCTION__,
151  NS_ConvertUTF16toUTF8(aTreeRootPath).get());
152  if (mWatchPath.IsEmpty()) {
153  // If the watch path is empty here, this means that the tree was loaded
154  // from a previous session. Set the watch path now.
155  mWatchPath.Assign(aTreeRootPath);
156  }
157 
158  // Now start watching
159  CFStringRef path =
160  CFStringCreateWithCString(NULL,
161  NS_ConvertUTF16toUTF8(mWatchPath).get(),
162  kCFStringEncodingUTF8);
163  CFArrayRef paths = CFArrayCreate(NULL, (const void **)&path, 1, NULL);
164 
165  // Setup callback reference
166  mContext = (FSEventStreamContext *) malloc(sizeof(FSEventStreamContext));
167  mContext->info = (void *)this;
168  mContext->version = 0;
169  mContext->retain = NULL;
170  mContext->release = NULL;
171  mContext->copyDescription = NULL;
172 
173  mStream = FSEventStreamCreate(NULL,
174  (FSEventStreamCallback)&FSEventCallback,
175  mContext,
176  paths,
177  kFSEventStreamEventIdSinceNow,
178  1.0, // lag in seconds
179  kFSEventStreamCreateFlagNone);
180 
181  FSEventStreamScheduleWithRunLoop(mStream,
182  CFRunLoopGetCurrent(),
183  kCFRunLoopDefaultMode);
184  // Now start the FSEvent stream
185  mIsWatching = FSEventStreamStart(mStream);
186  NS_ENSURE_TRUE(mIsWatching, NS_ERROR_UNEXPECTED);
187 
188  nsresult rv = mListener->OnWatcherStarted();
189  NS_ENSURE_SUCCESS(rv, rv);
190 
191  return NS_OK;
192 }
193 
nsCOMPtr< sbIFileSystemListener > mListener
#define SB_PRLOG_SETUP(x)
Definition: sbDebugUtils.h:115
return NS_OK
static void FSEventCallback(ConstFSEventStreamRef aStreamRef, void *aClientCallbackInfo, size_t aNumEvents, const char *const aEventPaths[], const FSEventStreamEventFlags aEventFlags[], const FSEventStreamEventId aEventIds[])
nsTArray< nsString > sbStringArray
NS_IMETHOD StopWatching(PRBool aShouldSaveSession)
NS_IMETHOD InitWithSession(const nsACString &aSessionGuid, sbIFileSystemListener *aListener)
nsRefPtr< sbFileSystemTree > mTree
function TRACE(s)
void OnFileSystemEvents(const sbStringArray &aEventPaths)
function Init()
NS_IMETHOD OnTreeReady(const nsAString &aTreeRootPath, sbStringArray &aDirPathArray)
_getSelectedPageStyle s i
NS_IMETHOD Init(sbIFileSystemListener *aListener, const nsAString &aRootPath, PRBool aIsRecursive)