Merge lp:~jan-hrdina/synapse-project/chromium-plugin into lp:synapse-project

Proposed by Jan Hrdina
Status: Merged
Merged at revision: 516
Proposed branch: lp:~jan-hrdina/synapse-project/chromium-plugin
Merge into: lp:synapse-project
Diff against target: 259 lines (+222/-0)
4 files modified
po/POTFILES.in (+1/-0)
src/plugins/Makefile.am (+1/-0)
src/plugins/chromium-plugin.vala (+219/-0)
src/ui/synapse-main.vala (+1/-0)
To merge this branch: bzr merge lp:~jan-hrdina/synapse-project/chromium-plugin
Reviewer Review Type Date Requested Status
Michal Hruby Approve
Review via email: mp+165620@code.launchpad.net

Description of the change

I've written Chromium Plugin for Chromium bookmarks support. Could you please look at it when you have time?

Thx!

To post a comment you must log in.
509. By Jan Hrdina

Add Chromium plugin into POTFILES.in

Revision history for this message
Michal Hruby (mhr3) wrote :

Hi, sorry this took so long to review, synapse has been lately on backburner, and could use more active maintainers :)

Nonetheless the branch looks good, just one thing - could you make the parse_bookmarks method async? Synapse wants to be super fast to startup and doing blocking io is not helping that goal.

review: Needs Fixing
510. By Jan Hrdina

Chromium Plugin parsing method made async

511. By Jan Hrdina

Merge upstream

Revision history for this message
Jan Hrdina (jan-hrdina) wrote :

Hi, I have made the parse_bookmarks method async so I believe the plugin is now ready for merging.

Revision history for this message
Michal Hruby (mhr3) wrote :

A method isn't async just by adding the "async" keyword, you actually have to yield inside it.

Anyway fixed and merged, thanks, and once again sorry this took so long.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'po/POTFILES.in'
2--- po/POTFILES.in 2012-03-18 18:55:40 +0000
3+++ po/POTFILES.in 2013-10-15 14:18:49 +0000
4@@ -20,6 +20,7 @@
5 src/plugins/banshee-plugin.vala
6 src/plugins/calculator-plugin.vala
7 src/plugins/chat-actions-plugin.vala
8+src/plugins/chromium-plugin.vala
9 src/plugins/command-plugin.vala
10 src/plugins/desktop-file-plugin.vala
11 src/plugins/devhelp-search.vala
12
13=== modified file 'src/plugins/Makefile.am'
14--- src/plugins/Makefile.am 2013-07-02 23:06:40 +0000
15+++ src/plugins/Makefile.am 2013-10-15 14:18:49 +0000
16@@ -32,6 +32,7 @@
17 banshee-plugin.vala \
18 calculator-plugin.vala \
19 chat-actions-plugin.vala \
20+ chromium-plugin.vala \
21 command-plugin.vala \
22 file-op-plugin.vala \
23 desktop-file-plugin.vala \
24
25=== added file 'src/plugins/chromium-plugin.vala'
26--- src/plugins/chromium-plugin.vala 1970-01-01 00:00:00 +0000
27+++ src/plugins/chromium-plugin.vala 2013-10-15 14:18:49 +0000
28@@ -0,0 +1,219 @@
29+/*
30+ * Copyright (C) 2013 Jan Hrdina <jan.hrdka@gmail.com>
31+ *
32+ * This program is free software: you can redistribute it and/or modify it
33+ * under the terms of the GNU General Public License as published by the
34+ * Free Software Foundation, either version 3 of the License, or
35+ * (at your option) any later version.
36+ *
37+ * This program is distributed in the hope that it will be useful, but
38+ * WITHOUT ANY WARRANTY; without even the implied warranty of
39+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
40+ * See the GNU General Public License for more details.
41+ *
42+ * You should have received a copy of the GNU General Public License along
43+ * with this program. If not, see <http://www.gnu.org/licenses/>.
44+ */
45+
46+namespace Synapse
47+{
48+
49+ public class ChromiumPlugin : Object, Activatable, ItemProvider
50+ {
51+ public bool enabled { get; set; default = true; }
52+
53+ public void activate ()
54+ {
55+
56+ }
57+
58+ public void deactivate ()
59+ {
60+
61+ }
62+
63+ private class BookmarkMatch : Object, Match, UriMatch
64+ {
65+ // from Match interface
66+ public string title { get; construct set; }
67+ public string description { get; set; default = ""; }
68+ public string icon_name { get; construct set; }
69+ public bool has_thumbnail { get; construct set; default = false; }
70+ public string thumbnail_path { get; construct set; }
71+ public MatchType match_type { get; construct set; }
72+
73+ // from UriMatch interface
74+ public string uri { get; set; }
75+ public QueryFlags file_type { get; set; }
76+ public string mime_type { get; set; }
77+
78+ private string? title_folded = null;
79+ private string? uri_folded = null;
80+
81+ public unowned string get_title_folded ()
82+ {
83+ if (title_folded == null) title_folded = title.casefold ();
84+ return title_folded;
85+ }
86+
87+ public unowned string get_uri_folded ()
88+ {
89+ if (uri_folded == null) uri_folded = uri.casefold ();
90+ return uri_folded;
91+ }
92+
93+ public BookmarkMatch.with_content (string name, string url)
94+ {
95+ Object (title: name,
96+ description: url,
97+ uri: url,
98+ match_type: MatchType.GENERIC_URI,
99+ has_thumbnail: false, icon_name: "text-html");
100+ }
101+ }
102+
103+ static void register_plugin ()
104+ {
105+ DataSink.PluginRegistry.get_default ().register_plugin (
106+ typeof (ChromiumPlugin),
107+ _ ("Chromium Plugin"),
108+ _ ("Browse and open Chromium bookmarks."),
109+ "chromium",
110+ register_plugin,
111+ Environment.find_program_in_path ("chromium") != null,
112+ _ ("Chromium is not installed")
113+ );
114+ }
115+
116+ static construct
117+ {
118+ register_plugin ();
119+ }
120+
121+ private Gee.List<BookmarkMatch> bookmarks;
122+
123+ construct
124+ {
125+ bookmarks = new Gee.ArrayList<BookmarkMatch> ();
126+ parse_bookmarks.begin ();
127+ }
128+
129+ private void full_search (Query q, ResultSet results,
130+ MatcherFlags flags = 0)
131+ {
132+ // try to match against global matchers and if those fail, try also exec
133+ var matchers = Query.get_matchers_for_query (q.query_string_folded, flags);
134+
135+ foreach (var bmk in bookmarks)
136+ {
137+ unowned string name = bmk.get_title_folded ();
138+ unowned string url = bmk.get_uri_folded ();
139+
140+ foreach (var matcher in matchers)
141+ {
142+ if (matcher.key.match (name))
143+ {
144+ results.add (bmk, matcher.value);
145+ break;
146+ }
147+ if (url != null && matcher.key.match (url))
148+ {
149+ results.add (bmk, matcher.value);
150+ break;
151+ }
152+ }
153+ }
154+ }
155+
156+ public bool handles_query (Query query)
157+ {
158+ return (QueryFlags.INTERNET in query.query_type);
159+ }
160+
161+ public async ResultSet? search (Query q) throws SearchError
162+ {
163+ var result = new ResultSet ();
164+
165+ if (q.query_string.length == 1)
166+ {
167+ var flags = MatcherFlags.NO_SUBSTRING | MatcherFlags.NO_PARTIAL |
168+ MatcherFlags.NO_FUZZY;
169+ full_search (q, result, flags);
170+ }
171+ else
172+ {
173+ full_search (q, result);
174+ }
175+
176+ q.check_cancellable ();
177+
178+ return result;
179+ }
180+
181+
182+ /* Bookmarks parsing methods */
183+
184+ private static bool is_container (Json.Object o, string container_string)
185+ {
186+ return o.get_string_member ("type") == container_string;
187+ }
188+
189+ private static bool is_bookmark (Json.Object o)
190+ {
191+ return o.has_member ("url");
192+ }
193+
194+ private static bool is_good (Json.Object o, Gee.HashSet<string> unwanted_scheme)
195+ {
196+ return !unwanted_scheme.contains (o.get_string_member ("url")
197+ .split (":", 1)[0]);
198+ }
199+
200+ private async void parse_bookmarks ()
201+ {
202+ var parser = new Json.Parser ();
203+ string fpath = GLib.Path.build_filename (Environment.get_user_config_dir (),
204+ "chromium", "Default", "Bookmarks");
205+
206+ string CONTAINER = "folder";
207+ Gee.HashSet<string> UNWANTED_SCHEME = new Gee.HashSet<string> ();
208+ UNWANTED_SCHEME.add ("data");
209+ UNWANTED_SCHEME.add ("place");
210+ UNWANTED_SCHEME.add ("javascript");
211+
212+ List<unowned Json.Node> folders = new List<Json.Node> ();
213+
214+ try
215+ {
216+ parser.load_from_file (fpath);
217+ var root_object = parser.get_root ().get_object ();
218+ folders.concat (root_object.get_member ("roots").get_object ()
219+ .get_member ("bookmark_bar").get_object ()
220+ .get_array_member ("children").get_elements ());
221+ folders.concat (root_object.get_member ("roots").get_object ()
222+ .get_member ("other").get_object ()
223+ .get_array_member ("children").get_elements ());
224+
225+ Json.Object o;
226+ foreach (var item in folders)
227+ {
228+ o = item.get_object ();
229+ if (is_bookmark (o) && is_good (o, UNWANTED_SCHEME))
230+ {
231+ bookmarks.add (new BookmarkMatch.with_content (
232+ o.get_string_member ("name"),
233+ o.get_string_member ("url")));
234+ }
235+ if (is_container (o, CONTAINER))
236+ {
237+ folders.concat(o.get_array_member ("children").get_elements ());
238+ }
239+ }
240+ }
241+ catch (Error err)
242+ {
243+ warning ("%s", err.message);
244+ }
245+ }
246+ }
247+}
248
249=== modified file 'src/ui/synapse-main.vala'
250--- src/ui/synapse-main.vala 2013-07-20 18:34:34 +0000
251+++ src/ui/synapse-main.vala 2013-10-15 14:18:49 +0000
252@@ -177,6 +177,7 @@
253 typeof (SelectionPlugin),
254 typeof (SshPlugin),
255 typeof (XnoiseActions),
256+ typeof (ChromiumPlugin),
257 // typeof (FileOpPlugin),
258 // typeof (PidginPlugin),
259 // typeof (ChatActions),