|
1 // -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 // This Source Code Form is subject to the terms of the Mozilla Public |
|
3 // License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
5 |
|
6 this.EXPORTED_SYMBOLS = ["RemoteAddonsParent"]; |
|
7 |
|
8 const Ci = Components.interfaces; |
|
9 const Cc = Components.classes; |
|
10 const Cu = Components.utils; |
|
11 |
|
12 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
13 Cu.import('resource://gre/modules/Services.jsm'); |
|
14 |
|
15 /** |
|
16 * This code listens for nsIContentPolicy hooks firing in child |
|
17 * processes. It then fires all hooks in the parent process and |
|
18 * returns the result to the child. |
|
19 */ |
|
20 let ContentPolicyParent = { |
|
21 /** |
|
22 * Some builtin policies will have already run in the child, and |
|
23 * there's no reason to run them in the parent. This is a list of |
|
24 * those policies. We assume that all child processes have the same |
|
25 * set of built-in policies. |
|
26 */ |
|
27 _policiesToIgnore: [], |
|
28 |
|
29 init: function() { |
|
30 let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] |
|
31 .getService(Ci.nsIMessageBroadcaster); |
|
32 ppmm.addMessageListener("Addons:ContentPolicy:IgnorePolicies", this); |
|
33 ppmm.addMessageListener("Addons:ContentPolicy:Run", this); |
|
34 |
|
35 Services.obs.addObserver(this, "xpcom-category-entry-added", true); |
|
36 Services.obs.addObserver(this, "xpcom-category-entry-removed", true); |
|
37 }, |
|
38 |
|
39 observe: function(aSubject, aTopic, aData) { |
|
40 switch (aTopic) { |
|
41 case "xpcom-category-entry-added": |
|
42 case "xpcom-category-entry-removed": |
|
43 if (aData == "content-policy") |
|
44 this.updatePolicies(); |
|
45 break; |
|
46 } |
|
47 }, |
|
48 |
|
49 /** |
|
50 * There's no need for the child process to inform us about the |
|
51 * shouldLoad hook if we don't have any policies in the parent to |
|
52 * run. This code iterates over the parent's policies, looking for |
|
53 * ones that should not be ignored. Based on that, it tells the |
|
54 * children whether it needs to be informed about the shouldLoad |
|
55 * hook. |
|
56 */ |
|
57 updatePolicies: function() { |
|
58 let needHook = false; |
|
59 |
|
60 let services = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager) |
|
61 .enumerateCategory("content-policy"); |
|
62 while (services.hasMoreElements()) { |
|
63 let item = services.getNext(); |
|
64 let name = item.QueryInterface(Components.interfaces.nsISupportsCString).toString(); |
|
65 |
|
66 if (this._policiesToIgnore.indexOf(name) == -1) { |
|
67 needHook = true; |
|
68 break; |
|
69 } |
|
70 } |
|
71 |
|
72 let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] |
|
73 .getService(Ci.nsIMessageBroadcaster); |
|
74 ppmm.broadcastAsyncMessage("Addons:ContentPolicy:NeedHook", { needed: needHook }); |
|
75 }, |
|
76 |
|
77 receiveMessage: function (aMessage) { |
|
78 switch (aMessage.name) { |
|
79 case "Addons:ContentPolicy:IgnorePolicies": |
|
80 this._policiesToIgnore = aMessage.data.policies; |
|
81 this.updatePolicies(); |
|
82 break; |
|
83 |
|
84 case "Addons:ContentPolicy:Run": |
|
85 return this.shouldLoad(aMessage.data, aMessage.objects); |
|
86 break; |
|
87 } |
|
88 }, |
|
89 |
|
90 shouldLoad: function(aData, aObjects) { |
|
91 let services = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager) |
|
92 .enumerateCategory("content-policy"); |
|
93 while (services.hasMoreElements()) { |
|
94 let item = services.getNext(); |
|
95 let name = item.QueryInterface(Components.interfaces.nsISupportsCString).toString(); |
|
96 if (this._policiesToIgnore.indexOf(name) != -1) |
|
97 continue; |
|
98 |
|
99 let policy = Cc[name].getService(Ci.nsIContentPolicy); |
|
100 try { |
|
101 let result = policy.shouldLoad(aData.contentType, |
|
102 aObjects.contentLocation, |
|
103 aObjects.requestOrigin, |
|
104 aObjects.node, |
|
105 aData.mimeTypeGuess, |
|
106 null); |
|
107 if (result != Ci.nsIContentPolicy.ACCEPT && result != 0) |
|
108 return result; |
|
109 } catch (e) {} |
|
110 } |
|
111 |
|
112 return Ci.nsIContentPolicy.ACCEPT; |
|
113 }, |
|
114 |
|
115 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), |
|
116 }; |
|
117 |
|
118 let RemoteAddonsParent = { |
|
119 initialized: false, |
|
120 |
|
121 init: function() { |
|
122 if (this.initialized) |
|
123 return; |
|
124 |
|
125 this.initialized = true; |
|
126 |
|
127 ContentPolicyParent.init(); |
|
128 }, |
|
129 }; |