Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/devtools.js

Issue 6393086494113792: Issue 154 - Added devtools panel showing blocked and blockable items (Closed)
Patch Set: Rebased Created Feb. 13, 2015, 4:16 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include.preload.js ('k') | metadata.chrome » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 let info = require("info");
19 if (info.platform == "chromium")
20 {
21 let {WhitelistFilter, ElemHideFilter} = require("filterClasses");
22 let {SpecialSubscription} = require("subscriptionClasses");
23 let {FilterStorage} = require("filterStorage");
24 let {defaultMatcher} = require("matcher");
25 let {FilterNotifier} = require("filterNotifier");
26 let {stringifyURL, isThirdParty} = require("url");
27
28 // Mapping of inspected tabs to their devpanel page
29 // and recorded items. We can't use a PageMap here,
30 // because data must persist after navigation/reload.
31 let panels = Object.create(null);
32
33 function getRequestInfo(request)
34 {
35 return {
36 url: request.url && stringifyURL(request.url),
37 type: request.type,
38 docDomain: request.docDomain
39 };
40 }
41
42 function getFilterInfo(filter)
43 {
44 if (!filter)
45 return null;
46
47 let userDefined = false;
48 let subscriptionTitle = null;
49
50 for (let subscription of filter.subscriptions)
51 {
52 if (!subscription.disabled)
53 {
54 if (subscription instanceof SpecialSubscription)
55 userDefined = true;
56 else
57 subscriptionTitle = subscription.title;
58 }
59 }
60
61 return {
62 text: filter.text,
63 whitelisted: filter instanceof WhitelistFilter,
64 userDefined: userDefined,
65 subscription: subscriptionTitle
66 };
67 }
68
69 function addRecord(panel, request, filter)
70 {
71 panel.page.sendMessage({
72 type: "add-record",
73 request: getRequestInfo(request),
74 filter: getFilterInfo(filter)
75 });
76
77 panel.records.push({
78 request: request,
79 filter: filter
80 });
81 }
82
83 function matchRequest(request)
84 {
85 return defaultMatcher.matchesAny(
86 stringifyURL(request.url),
87 request.type,
88 request.docDomain,
89 isThirdParty(request.url, request.docDomain),
90 request.sitekey
91 );
92 }
93
94 /**
95 * Logs a request in the devtools panel.
96 *
97 * @param {Page} [page] The page the request occured on
98 * @param {URL] [url] The URL of the request
99 * @param {string} [type] The request type
100 * @param {string} [docDomain] The IDN-decoded hostname of the document
101 * @param {string} [sitekey] The active sitekey if there is any
102 * @param {filter} [filter] The matched filter or null if there is no match
103 */
104 function logRequest(page, url, type, docDomain, sitekey, filter)
105 {
106 let panel = panels[page._id];
107 if (panel)
108 {
109 let request = {
110 url: url,
111 type: type,
112 docDomain: docDomain,
113 sitekey: sitekey
114 };
115
116 addRecord(panel, request, filter);
117 }
118 }
119 exports.logRequest = logRequest;
120
121 /**
122 * Logs active element hiding filters in the devtools panel.
123 *
124 * @param {Page} [page] The page the elements were hidden on
125 * @param {string[]} [selectors] The CSS selectors of active elemhide filters
126 * @param {string} [docDomain] The IDN-decoded hostname of the document
127 */
128 function logHiddenElements(page, selectors, docDomain)
129 {
130 let panel = panels[page._id];
131 if (panel)
132 {
133 for (let subscription of FilterStorage.subscriptions)
134 {
135 if (subscription.disabled)
136 continue;
137
138 for (let filter of subscription.filters)
139 {
140 if (!(filter instanceof ElemHideFilter))
141 continue;
142 if (selectors.indexOf(filter.selector) == -1)
143 continue;
144 if (!filter.isActiveOnDomain(docDomain))
145 continue;
146 if (panel.records.some(record => record.request.type == "ELEMHIDE" &&
147 record.request.docDomain == docDomain &&
148 record.filter.selector == filter.sele ctor))
149 continue;
150
151 addRecord(panel, {type: "ELEMHIDE", docDomain: docDomain}, filter);
152 }
153 }
154 }
155 };
156 exports.logHiddenElements = logHiddenElements;
157
158 /**
159 * Starts to record items and shows them in the devtools panel.
160 *
161 * @param {Page} [panelPage] The page of the the devtools panel
162 * @param {number} [inpectedTabId] The ID of the tab to record item from
163 */
164 function initDevToolsPanel(panelPage, inpectedTabId)
165 {
166 panels[inpectedTabId] = {page: panelPage, records: []};
167
168 // Forget about this devtools panel and the items recorded there
169 // so far, when the panel (not the tab it is inspecting) is closed.
170 function onRemoved(tabId)
171 {
172 if (tabId == panelPage._id)
173 {
174 delete panels[inpectedTabId];
175 chrome.tabs.onRemoved.removeListener(onRemoved);
176 }
177 }
178 chrome.tabs.onRemoved.addListener(onRemoved);
179 }
180 exports.initDevToolsPanel = initDevToolsPanel;
181
182 /**
183 * Checks whether a page is inspected by the devtools panel.
184 *
185 * @param {Page} [page]
186 * @return {Boolean}
187 */
188 function hasDevToolsPanel(page)
189 {
190 return page._id in panels;
191 }
192 exports.hasDevToolsPanel = hasDevToolsPanel;
193
194 chrome.webNavigation.onBeforeNavigate.addListener(function(details)
195 {
196 let panel = panels[details.tabId];
197 if (panel && details.frameId == 0)
198 {
199 // We have to flush the in-memory cache on page load.
200 // Otherwise requests answered from the in-memory cache
201 // will not be shown in the devtools panel.
202 chrome.webRequest.handlerBehaviorChanged();
203
204 panel.records = [];
205 panel.page.sendMessage({type: "reset"});
206 }
207 });
208
209 FilterNotifier.addListener(function(action, filter)
210 {
211 if (action != "filter.added" && action != "filter.removed")
212 return;
213
214 for (let tabId in panels)
215 {
216 let panel = panels[tabId];
217
218 for (let i = 0; i < panel.records.length; i++)
219 {
220 let record = panel.records[i];
221
222 if (action == "filter.added")
223 {
224 if (record.request.type == "ELEMHIDE")
225 continue;
226
227 if (matchRequest(record.request) != filter)
228 continue;
229
230 record.filter = filter;
231 }
232
233 if (action == "filter.removed")
234 {
235 if (record.filter != filter)
236 continue;
237
238 if (record.request.type == "ELEMHIDE")
239 {
240 panel.page.sendMessage({
241 type: "remove-record",
242 index: i
243 });
244 panel.records.splice(i--, 1);
245 continue;
246 }
247
248 record.filter = matchRequest(record.request);
249 }
250
251 panel.page.sendMessage({
252 type: "update-record",
253 index: i,
254 request: getRequestInfo(record.request),
255 filter: getFilterInfo(record.filter)
256 });
257 }
258 }
259 });
260 }
261 else
262 {
263 exports.logRequest = () => {};
264 exports.logHiddenElements = () => {};
265 exports.initDevToolsPanel = () => {};
266 exports.hasDevToolsPanel = () => false;
267 }
OLDNEW
« no previous file with comments | « include.preload.js ('k') | metadata.chrome » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld