Commits

ryanackley committed 885c8fd Merge
  • Participants
  • Parent commits 131a8fc, 53b9d85

Comments (0)

Files changed (10)

File Win/FileWatcherTaskWin.cpp

+#include <string>
+#include "FileWatcherTaskWin.h"
+#include "variant_list.h"
+
+
+
+FileWatcherTaskWin::FileWatcherTaskWin(std::string path, FB::JSObjectPtr callback)
+{
+	stop = false;
+
+	WCHAR widePathBuf[2048];
+	int wpBufSize = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, widePathBuf, 2048);
+	
+	m_path = widePathBuf;
+	m_callback = callback;
+
+	ZeroMemory(&m_ol, sizeof(m_ol));
+
+	m_handle = CreateFile(m_path.c_str(), 
+								FILE_LIST_DIRECTORY, 
+								FILE_SHARE_READ | FILE_SHARE_WRITE,
+								NULL,
+								OPEN_EXISTING,
+								FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+								NULL);
+	m_ol.hEvent = this;
+}
+void FileWatcherTaskWin::StartWatching()
+{
+	m_thread = boost::thread(boost::bind(&FileWatcherTaskWin::StartAlertLoop, this));
+	QueueUserAPC(FileWatcherTaskWin::InitDirectoryWatcher, m_thread.native_handle(), (ULONG_PTR)this);
+}
+void FileWatcherTaskWin::StartAlertLoop()
+{
+	while (!stop)
+	{
+		SleepEx(INFINITE, TRUE);
+	}
+}
+void CALLBACK FileWatcherTaskWin::InitDirectoryWatcher(ULONG_PTR arg)
+{
+	FileWatcherTaskWin* task = (FileWatcherTaskWin*)arg;
+	BOOL success = task->ListenForFileEvents();
+}
+
+BOOL FileWatcherTaskWin::ListenForFileEvents()
+{
+	DWORD dwBytes=0;
+
+	return ReadDirectoryChangesW(m_handle, m_buffer, 4096, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytes, &m_ol, &WatcherCallback);
+}
+
+void CALLBACK FileWatcherTaskWin::WatcherCallback(DWORD dwErrorCode,DWORD bytesInBuf,LPOVERLAPPED lpOverlapped)
+{
+	FileWatcherTaskWin* task = (FileWatcherTaskWin*)lpOverlapped->hEvent; 
+	if (bytesInBuf > 0)
+	{
+		BOOL moreToRead = true;
+		char* readFrom = task->m_buffer;
+		while(moreToRead)
+		{
+			FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)readFrom;
+			std::wstring fileName(fni->FileName, fni->FileNameLength/sizeof(WCHAR));
+			std::wstring wideFinalPath = task->m_path + L"\\" + fileName;
+
+			char utf8Buf[2048];
+			int pathLength = WideCharToMultiByte(CP_UTF8, 0, wideFinalPath.c_str(), -1, utf8Buf, 2048, NULL, NULL);
+			std::string finalPath = utf8Buf;
+			
+			task->m_callback->Invoke("", FB::variant_list_of(finalPath));
+			if (!fni->NextEntryOffset)
+			{
+				moreToRead = false;
+			}
+			else
+			{
+				readFrom += fni->NextEntryOffset;
+			}
+		}
+	}
+	BOOL success = task->ListenForFileEvents();
+}
+void CALLBACK FileWatcherTaskWin::TerminateWatch(ULONG_PTR arg)
+{
+	FileWatcherTaskWin* task = (FileWatcherTaskWin*)arg;
+	task->CloseHandlesStopAlertLoop();
+}
+void FileWatcherTaskWin::CloseHandlesStopAlertLoop()
+{
+	CancelIo(m_handle);
+	CloseHandle(m_handle);
+	this->stop = true;
+}
+void FileWatcherTaskWin::StopWatching()
+{
+	QueueUserAPC(FileWatcherTaskWin::TerminateWatch, m_thread.native_handle(), (ULONG_PTR)this);
+	// 5 seconds should be plenty of time
+	m_thread.timed_join(boost::posix_time::seconds(5));
+}

File Win/FileWatcherTaskWin.h

+#pragma once
+
+#include "JSObject.h"
+#include "windows.h"
+
+class FileWatcherTaskWin
+{
+public:
+	FileWatcherTaskWin(std::string path, FB::JSObjectPtr callback);
+	~FileWatcherTaskWin(){};
+
+	void StartWatching();
+	void StopWatching();
+
+private:
+
+	static void CALLBACK WatcherCallback(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,	LPOVERLAPPED lpOverlapped);
+
+	static void CALLBACK InitDirectoryWatcher(ULONG_PTR arg);
+
+	static void CALLBACK TerminateWatch(ULONG_PTR arg);
+	
+	void StartAlertLoop();
+	BOOL ListenForFileEvents();
+	void CloseHandlesStopAlertLoop();
+	//bool ShouldStop();
+	
+	HANDLE m_handle;
+	char m_buffer[4096];
+	
+	bool stop;
+	std::wstring m_path;
+	FB::JSObjectPtr m_callback;
+	OVERLAPPED m_ol;
+	boost::thread m_thread;
+};

File Win/FileWatcherWin.cpp

+#include "FileWatcherWin.h"
+
+FileWatcher* FileWatcher::get()
+{
+    static FileWatcherWin inst;
+    return &inst;
+}
+
+void FileWatcherWin::WatchFile(std::string key, std::string path, FB::JSObjectPtr callback)
+{
+	FileWatcherTaskWin* task = watchers[key];
+	if (!task)
+	{
+		boost::filesystem::path p(path);
+		if (is_directory(p))
+		{
+			task = new FileWatcherTaskWin(path,callback);
+			task->StartWatching();
+			watchers[key] = task;
+		}
+	}
+
+}
+void FileWatcherWin::StopWatching(std::string key)
+{
+	FileWatcherTaskWin* task = watchers[key];
+	if (task)
+	{
+		task->StopWatching();
+		watchers.erase(key);
+		delete task;
+	}
+}

File Win/FileWatcherWin.h

+#pragma once
+
+#define BOOST_FILESYSTEM_VERSION 3
+#include <map>
+#include "../FileWatcher.h"
+#include "FileWatcherTaskWin.h"
+#include <boost/filesystem.hpp>
+
+
+class FileWatcherWin : public FileWatcher
+{
+public:
+	void WatchFile(std::string key, std::string path, FB::JSObjectPtr callback);
+    void StopWatching(std::string key);
+
+protected:
+	FileWatcherWin(void){};
+	~FileWatcherWin(void){};
+	friend class FileWatcher;
+private:
+	std::map<std::string,FileWatcherTaskWin*> watchers;
+};

File X11/DialogManagerX11.cpp~

+#include <string>
+#include <boost/thread.hpp>
+
+#include "DialogManagerX11.h"
+#include "BrowserHost.h"
+#include "PluginWindowX11.h"
+
+DialogManager* DialogManager::get()
+{
+    static DialogManagerX11 inst;
+    return &inst;
+}
+
+void DialogManagerX11::OpenFolderDialog(const FB::BrowserHostPtr& host, FB::PluginWindow* win, const PathCallback& cb)
+{
+    FB::PluginWindowX11* x11Win = dynamic_cast<FB::PluginWindowX11*>(win);
+    GdkNativeWindow nativeWin = x11Win->getBrowserWindow();
+    GtkWindow* gtkWin = gdk_window_lookup(nativeWin);
+    host->ScheduleOnMainThread(boost::shared_ptr<DialogManagerX11>(), boost::bind(&DialogManagerX11::_showFolderDialog, this, gtkWin, cb));
+}
+
+void DialogManagerX11::_showFolderDialog(GtkWindow* win, const PathCallback& cb)
+{
+    std::string out;
+    GtkWidget *dialog;
+    dialog = gtk_file_chooser_dialog_new ("Open File",
+				      win,
+				      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+				      NULL);
+    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+        char *filename;
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+        out = filename;
+        g_free (filename);
+    }
+    gtk_widget_destroy (dialog);
+    cb(out);
+}

File X11/DialogManagerX11.h~

+//  Created by Ryan Ackley on 4/10/12.
+//  Copyright (c) 2012 Benryan Software Inc. All rights reserved.
+//
+
+#ifndef DialogManagerX11_h__
+#define DialogManagerX11_h__
+
+#include <boost/noncopyable.hpp>
+#include <string>
+#include <gtk/gtk.h>
+
+#include "../DialogManager.h"
+
+class DialogManagerX11 : public DialogManager
+{
+public:
+    void OpenFolderDialog(const FB::BrowserHostPtr& host, FB::PluginWindow* win, const PathCallback& cb);
+    void _showFolderDialog(GtkWindow* win, const PathCallback& cb);
+    
+protected:
+    DialogManagerX11() {};
+    ~DialogManagerX11() {};
+    friend class DialogManager;
+};
+#endif // DialogManagerX11_h__

File X11/FileWatcherTaskX11.cpp

+/*
+ * FileWatcherTaskX11.cpp
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+
+
+#include "FileWatcherTaskX11.h"
+#include <boost/thread.hpp>
+#include <sys/inotify.h>
+#include <iostream>
+#include "variant_list.h"
+
+#define EVENT_SIZE  ( sizeof (struct inotify_event) )
+#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
+
+using namespace boost::filesystem;
+
+void FileWatcherTaskX11::Watch(boost::filesystem::path p, FB::JSObjectPtr callback)
+{
+	boost::thread thread = boost::thread(boost::bind(&FileWatcherTaskX11::ListenForFileEvents, this, p, callback));
+	thread.detach();
+}
+
+void FileWatcherTaskX11::ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback)
+{
+	int length;//, i = 0;
+	int fd;
+	int wd;
+	char buffer[EVENT_BUF_LEN];
+
+	/*creating the INOTIFY instance*/
+	fd = inotify_init();
+
+	/*checking for error*/
+	if ( fd < 0 ) {
+		std::cerr << "inotify_init" ;
+	}
+
+	std::map<int, boost::filesystem::path*> wdMap;
+
+	/*adding the  directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
+	//wd = inotify_add_watch( fd, path.c_str(), IN_MODIFY | IN_MOVED_TO);
+	this->AddWatchToDir(fd, path, wdMap );
+
+	/*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/
+	while (!this->_ShouldStop())
+	{
+		int i = 0;
+		struct timeval time;
+		fd_set set;
+
+		time.tv_sec = 10;
+		time.tv_usec = 0;
+
+		FD_ZERO(&set);
+		FD_SET(fd, &set);
+
+		int sr = select (FD_SETSIZE, &set, NULL, NULL, &time);
+		if (!sr) //timeout
+		{
+			continue;
+		}
+		else if (sr > 0)
+		{
+			length = read( fd, buffer, EVENT_BUF_LEN );
+
+			/*checking for error*/
+			if ( length < 0 )
+			{
+				std::cerr << "read";
+			}
+
+			/*actually read return the list of change events happens. Here, read the change event one by one and process it accordingly.*/
+			while ( i < length )
+			{
+				struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
+				if ( event->len )
+				{
+					if ( ((event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO)) &&  !(event->mask & IN_ISDIR) )
+					{
+						std::string filename = event->name;
+						if (filename[0] != '.')
+						{
+							boost::filesystem::path* root = wdMap[event->wd];
+							boost::filesystem::path fsPath = *root / filename;
+							callback->Invoke("", FB::variant_list_of(fsPath.generic_string()));
+						}
+					}
+				}
+				i += EVENT_SIZE + event->len;
+			}
+		}
+		else
+		{
+			std::cerr << "select";
+			break;
+		}
+	}
+	/*removing the “/tmp” directory from the watch list.*/
+	std::map<int, boost::filesystem::path*>::iterator it;
+	for (it = wdMap.begin(); it != wdMap.end(); it++)
+	{
+		inotify_rm_watch( fd, (*it).first );
+		delete (*it).second;
+	}
+	//inotify_rm_watch( fd, wd );
+
+	/*closing the INOTIFY instance*/
+	close( fd );
+}
+
+void FileWatcherTaskX11::AddWatchToDir(int fd, boost::filesystem::path p, std::map<int, boost::filesystem::path*> &watchDescriptors)
+{
+	int wd = inotify_add_watch( fd, p.generic_string().c_str(), IN_MODIFY | IN_MOVED_TO);
+	watchDescriptors[wd] = new path(p);
+
+	directory_iterator di(p);
+	directory_iterator eos;
+
+	while(di != eos)
+	{
+		directory_entry de = *di;
+		if (is_directory(de.status())){
+			this->AddWatchToDir(fd, de.path(), watchDescriptors);
+		}
+		di++;
+	}
+}
+
+void FileWatcherTaskX11::StopWatching()
+{
+	this->stop = 1;
+}
+
+bool FileWatcherTaskX11::_ShouldStop()
+{
+	return this->stop != 0;
+}
+
+
+
+

File X11/FileWatcherTaskX11.h

+/*
+ * FileWatcherTaskX11.h
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#ifndef FILEWATCHERTASKX11_H_
+#define FILEWATCHERTASKX11_H_
+#define BOOST_FILESYSTEM_VERSION 3
+
+#include "JSObject.h"
+#include <boost/filesystem.hpp>
+
+class FileWatcherTaskX11 {
+public:
+	FileWatcherTaskX11(){stop = 0;};
+	~FileWatcherTaskX11(){};
+	void Watch(boost::filesystem::path path, FB::JSObjectPtr callback);
+	void StopWatching();
+
+private:
+	void ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback);
+	void AddWatchToDir(int fd, boost::filesystem::path path, std::map<int, boost::filesystem::path*> &watchDescriptors);
+	bool _ShouldStop();
+	int stop;
+};
+
+#endif /* FILEWATCHERTASKX11_H_ */

File X11/FileWatcherX11.cpp

+/*
+ * FileWatcherX11.cpp
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#include "FileWatcherX11.h"
+
+FileWatcher* FileWatcher::get()
+{
+    static FileWatcherX11 inst;
+    return &inst;
+}
+
+void FileWatcherX11::WatchFile(std::string key, std::string path, FB::JSObjectPtr callback)
+{
+	FileWatcherTaskX11* task = watchers[key];
+	if (!task)
+	{
+		boost::filesystem::path p(path);
+		if (is_directory(p))
+		{
+			task = new FileWatcherTaskX11();
+			task->Watch(p, callback);
+			watchers[key] = task;
+		}
+	}
+
+}
+void FileWatcherX11::StopWatching(std::string key)
+{
+	FileWatcherTaskX11* task = watchers[key];
+	if (task)
+	{
+		task->StopWatching();
+		watchers.erase(key);
+		delete task;
+	}
+}

File X11/FileWatcherX11.h

+/*
+ * FileWatcherX11.h
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#ifndef FILEWATCHERX11_H_
+#define FILEWATCHERX11_H_
+
+#include <map>
+#include "../FileWatcher.h"
+#include "FileWatcherTaskX11.h"
+
+class FileWatcherX11 : public FileWatcher{
+
+public:
+    void WatchFile(std::string key, std::string path, FB::JSObjectPtr callback);
+    void StopWatching(std::string key);
+protected:
+	FileWatcherX11(){};
+	virtual ~FileWatcherX11(){};
+	friend class FileWatcher;
+private:
+	std::map<std::string,FileWatcherTaskX11*> watchers;
+};
+
+#endif /* FILEWATCHERX11_H_ */