int     ImportBookmarksChrome(FileInfo _fileName, List <Fiche> _createdTags, List <Fiche> _complexNameTags)
        {
            // Attempt to parse JSON file
            WebServices.JSON            parser = new WebServices.JSON();
            WebServices.JSON.JSONObject root   = null;
            try {
                using (StreamReader R = _fileName.OpenText()) {
                    root = parser.ReadJSON(R);
                }
            } catch (Exception _e) {
                throw new Exception("Failed to parse JSON file!", _e);
            }

            // Read bookmarks
            Bookmark.ms_tags            = _createdTags;
            Bookmark.ms_complexNameTags = _complexNameTags;
            List <Bookmark> bookmarks = new List <Bookmark>();

            try {
                root = root["root"]["roots"];                   // Fetch the actual root
                foreach (object value in root.AsDictionary.Values)
                {
                    WebServices.JSON.JSONObject rootFolder = value as WebServices.JSON.JSONObject;
                    if (rootFolder != null)
                    {
                        // Add a new root folder containing bookmarks
                        bookmarks.Add(new Bookmark(m_owner.Database, null, rootFolder, bookmarks));
                    }
                }
            } catch (Exception _e) {
                throw new Exception("Failed to parse bookmarks!", _e);
            }

            // Now convert bookmarks into fiches
            int successfullyImportedBookmarksCounter = 0;

            foreach (Bookmark bookmark in bookmarks)
            {
                try {
                    if (bookmark.m_parent == null)
                    {
                        continue;                               // Don't create root folders...
                    }
                    // Reading the fiche property will create it and create its parent tags as well...
                    Fiche F = bookmark.Fiche;

                    successfullyImportedBookmarksCounter++;
                } catch (Exception _e) {
                    throw new Exception("Failed to parse bookmarks!", _e);
                }
            }

            return(successfullyImportedBookmarksCounter);
        }
            public void     RecurseImportBookmarks(Bookmark _parent, WebServices.JSON.JSONObject _object, List <Bookmark> _bookmarks)
            {
                if (_object == null)
                {
                    return;
                }
//					throw new Exception( "Invalid JSON object!" );

                if (_object.IsDictionary)
                {
                    // Create all bookmark objects in the dictionary
                    Dictionary <string, object> dictionary = _object.AsDictionary;
                    foreach (string key in dictionary.Keys)
                    {
                        WebServices.JSON.JSONObject bookmarkObject = dictionary[key] as WebServices.JSON.JSONObject;
                        if (bookmarkObject == null)
                        {
                            continue;                                   // Can't parse value
                        }
                        Bookmark bookmark = new Bookmark(m_database, _parent, bookmarkObject, _bookmarks);
                        _bookmarks.Add(bookmark);
                        _parent.m_children.Add(bookmark);
                    }
                }
                else if (_object.IsArray)
                {
                    // Create all bookmark objects in the array
                    List <object> array = _object.AsArray;
                    foreach (object element in array)
                    {
                        WebServices.JSON.JSONObject bookmarkObject = element as WebServices.JSON.JSONObject;
                        if (bookmarkObject == null)
                        {
                            continue;                                   // Can't parse value
                        }
                        // Each element must be a dictionary of properties for the bookmark
                        Bookmark bookmark = new Bookmark(m_database, _parent, bookmarkObject, _bookmarks);
                        _bookmarks.Add(bookmark);
                        _parent.m_children.Add(bookmark);
                    }
                }
                else
                {
                    throw new Exception("Unsupported JSON object type!");
                }
            }
            public Bookmark(FichesDB _database, Bookmark _parent, WebServices.JSON.JSONObject _JSON, List <Bookmark> _bookmarks)
            {
                m_database = _database;
                m_parent   = _parent;
                if (_JSON == null || !_JSON.IsDictionary)
                {
                    throw new Exception("Invalid JSON object type!");
                }

                Dictionary <string, object> dictionary = _JSON.AsDictionary;

                foreach (string key in dictionary.Keys)
                {
                    switch (key)
                    {
                    case "name":
                        m_name = dictionary[key] as string;
                        break;

                    case "date_added":
                        // From https://stackoverflow.com/questions/19074423/how-to-parse-the-date-added-field-in-chrome-bookmarks-file
                        string strTicks = dictionary[key] as string;
                        long   microseconds;
                        if (long.TryParse(strTicks, out microseconds))
                        {
                            long milliseconds = microseconds / 1000;
                            long seconds      = milliseconds / 1000;
                            long minutes      = seconds / 60;
                            long hours        = minutes / 60;
                            long days         = hours / 24;

                            TimeSpan delay = new TimeSpan((int)days, (int)(hours % 24), (int)(minutes % 60), (int)(seconds % 60), (int)(milliseconds % 1000));
                            m_dateAdded = new DateTime(1601, 1, 1) + delay;
                        }
                        break;

                    case "guid":
                        string strGUID = dictionary[key] as string;
                        Guid.TryParse(strGUID, out m_GUID);
                        break;

                    case "url":
                        string strURL = dictionary[key] as string;
                        m_URL = WebHelpers.CreateCanonicalURL(strURL);
                        break;

                    case "children":
                        RecurseImportBookmarks(this, dictionary[key] as WebServices.JSON.JSONObject, _bookmarks);
                        break;

                    case "type":
                        string strType = dictionary[key] as string;
                        switch (strType)
                        {
                        case "url": m_type = TYPE.URL; break;

                        case "folder": m_type = TYPE.FOLDER; break;
                        }
                        break;

                    default:
                        // Try import children...
                        RecurseImportBookmarks(this, dictionary[key] as WebServices.JSON.JSONObject, _bookmarks);
                        break;
                    }
                }
            }