Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsIURI.h"
8 #include "nsMaiHyperlink.h"
10 using namespace mozilla::a11y;
12 /* MaiAtkHyperlink */
14 #define MAI_TYPE_ATK_HYPERLINK (mai_atk_hyperlink_get_type ())
15 #define MAI_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
16 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
17 #define MAI_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
18 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
19 #define MAI_IS_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
20 MAI_TYPE_ATK_HYPERLINK))
21 #define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
22 MAI_TYPE_ATK_HYPERLINK))
23 #define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
24 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
26 /**
27 * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace,
28 * for AtkHyperlink
29 */
31 struct MaiAtkHyperlink
32 {
33 AtkHyperlink parent;
35 /*
36 * The MaiHyperlink whose properties and features are exported via this
37 * hyperlink instance.
38 */
39 MaiHyperlink *maiHyperlink;
40 };
42 struct MaiAtkHyperlinkClass
43 {
44 AtkHyperlinkClass parent_class;
45 };
47 GType mai_atk_hyperlink_get_type(void);
49 G_BEGIN_DECLS
50 /* callbacks for AtkHyperlink */
51 static void classInitCB(AtkHyperlinkClass *aClass);
52 static void finalizeCB(GObject *aObj);
54 /* callbacks for AtkHyperlink virtual functions */
55 static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex);
56 static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
57 static gint getEndIndexCB(AtkHyperlink *aLink);
58 static gint getStartIndexCB(AtkHyperlink *aLink);
59 static gboolean isValidCB(AtkHyperlink *aLink);
60 static gint getAnchorCountCB(AtkHyperlink *aLink);
61 G_END_DECLS
63 static gpointer parent_class = nullptr;
64 static Accessible*
65 get_accessible_hyperlink(AtkHyperlink *aHyperlink);
67 GType
68 mai_atk_hyperlink_get_type(void)
69 {
70 static GType type = 0;
72 if (!type) {
73 static const GTypeInfo tinfo = {
74 sizeof(MaiAtkHyperlinkClass),
75 (GBaseInitFunc)nullptr,
76 (GBaseFinalizeFunc)nullptr,
77 (GClassInitFunc)classInitCB,
78 (GClassFinalizeFunc)nullptr,
79 nullptr, /* class data */
80 sizeof(MaiAtkHyperlink), /* instance size */
81 0, /* nb preallocs */
82 (GInstanceInitFunc)nullptr,
83 nullptr /* value table */
84 };
86 type = g_type_register_static(ATK_TYPE_HYPERLINK,
87 "MaiAtkHyperlink",
88 &tinfo, GTypeFlags(0));
89 }
90 return type;
91 }
93 MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) :
94 mHyperlink(aHyperLink),
95 mMaiAtkHyperlink(nullptr)
96 {
97 }
99 MaiHyperlink::~MaiHyperlink()
100 {
101 if (mMaiAtkHyperlink) {
102 MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
103 g_object_unref(mMaiAtkHyperlink);
104 }
105 }
107 AtkHyperlink*
108 MaiHyperlink::GetAtkHyperlink(void)
109 {
110 NS_ENSURE_TRUE(mHyperlink, nullptr);
112 if (mMaiAtkHyperlink)
113 return mMaiAtkHyperlink;
115 if (!mHyperlink->IsLink())
116 return nullptr;
118 mMaiAtkHyperlink =
119 reinterpret_cast<AtkHyperlink *>
120 (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
121 NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
122 NS_ENSURE_TRUE(mMaiAtkHyperlink, nullptr);
124 /* be sure to initialize it with "this" */
125 MaiHyperlink::Initialize(mMaiAtkHyperlink, this);
127 return mMaiAtkHyperlink;
128 }
130 /* static */
132 /* remember to call this static function when a MaiAtkHyperlink
133 * is created
134 */
136 nsresult
137 MaiHyperlink::Initialize(AtkHyperlink *aObj, MaiHyperlink *aHyperlink)
138 {
139 NS_ENSURE_ARG(MAI_IS_ATK_HYPERLINK(aObj));
140 NS_ENSURE_ARG(aHyperlink);
142 /* initialize hyperlink */
143 MAI_ATK_HYPERLINK(aObj)->maiHyperlink = aHyperlink;
144 return NS_OK;
145 }
147 /* static functions for ATK callbacks */
149 void
150 classInitCB(AtkHyperlinkClass *aClass)
151 {
152 GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
154 parent_class = g_type_class_peek_parent(aClass);
156 aClass->get_uri = getUriCB;
157 aClass->get_object = getObjectCB;
158 aClass->get_end_index = getEndIndexCB;
159 aClass->get_start_index = getStartIndexCB;
160 aClass->is_valid = isValidCB;
161 aClass->get_n_anchors = getAnchorCountCB;
163 gobject_class->finalize = finalizeCB;
164 }
166 void
167 finalizeCB(GObject *aObj)
168 {
169 NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
170 if (!MAI_IS_ATK_HYPERLINK(aObj))
171 return;
173 MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
174 maiAtkHyperlink->maiHyperlink = nullptr;
176 /* call parent finalize function */
177 if (G_OBJECT_CLASS (parent_class)->finalize)
178 G_OBJECT_CLASS (parent_class)->finalize(aObj);
179 }
181 gchar *
182 getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
183 {
184 Accessible* hyperlink = get_accessible_hyperlink(aLink);
185 NS_ENSURE_TRUE(hyperlink, nullptr);
187 nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
188 if (!uri)
189 return nullptr;
191 nsAutoCString cautoStr;
192 nsresult rv = uri->GetSpec(cautoStr);
193 NS_ENSURE_SUCCESS(rv, nullptr);
195 return g_strdup(cautoStr.get());
196 }
198 AtkObject *
199 getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
200 {
201 Accessible* hyperlink = get_accessible_hyperlink(aLink);
202 NS_ENSURE_TRUE(hyperlink, nullptr);
204 Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
205 NS_ENSURE_TRUE(anchor, nullptr);
207 AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor);
208 //no need to add ref it, because it is "get" not "ref"
209 return atkObj;
210 }
212 gint
213 getEndIndexCB(AtkHyperlink *aLink)
214 {
215 Accessible* hyperlink = get_accessible_hyperlink(aLink);
216 NS_ENSURE_TRUE(hyperlink, -1);
218 return static_cast<gint>(hyperlink->EndOffset());
219 }
221 gint
222 getStartIndexCB(AtkHyperlink *aLink)
223 {
224 Accessible* hyperlink = get_accessible_hyperlink(aLink);
225 NS_ENSURE_TRUE(hyperlink, -1);
227 return static_cast<gint>(hyperlink->StartOffset());
228 }
230 gboolean
231 isValidCB(AtkHyperlink *aLink)
232 {
233 Accessible* hyperlink = get_accessible_hyperlink(aLink);
234 NS_ENSURE_TRUE(hyperlink, FALSE);
236 return static_cast<gboolean>(hyperlink->IsLinkValid());
237 }
239 gint
240 getAnchorCountCB(AtkHyperlink *aLink)
241 {
242 Accessible* hyperlink = get_accessible_hyperlink(aLink);
243 NS_ENSURE_TRUE(hyperlink, -1);
245 return static_cast<gint>(hyperlink->AnchorCount());
246 }
248 // Check if aHyperlink is a valid MaiHyperlink, and return the
249 // HyperLinkAccessible related.
250 Accessible*
251 get_accessible_hyperlink(AtkHyperlink *aHyperlink)
252 {
253 NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
254 MaiHyperlink * maiHyperlink =
255 MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
256 NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
257 NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
258 return maiHyperlink->GetAccHyperlink();
259 }