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 * 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/. */
6 #ifndef MOZILLA_GFX_USERDATA_H_
7 #define MOZILLA_GFX_USERDATA_H_
9 #include <stdlib.h>
10 #include "Types.h"
11 #include "mozilla/Assertions.h"
13 namespace mozilla {
14 namespace gfx {
16 struct UserDataKey {
17 int unused;
18 };
20 /* this class is basically a clone of the user data concept from cairo */
21 class UserData
22 {
23 typedef void (*destroyFunc)(void *data);
24 public:
25 UserData() : count(0), entries(nullptr) {}
27 /* Attaches untyped userData associated with key. destroy is called on destruction */
28 void Add(UserDataKey *key, void *userData, destroyFunc destroy)
29 {
30 for (int i=0; i<count; i++) {
31 if (key == entries[i].key) {
32 if (entries[i].destroy) {
33 entries[i].destroy(entries[i].userData);
34 }
35 entries[i].userData = userData;
36 entries[i].destroy = destroy;
37 return;
38 }
39 }
41 // We could keep entries in a std::vector instead of managing it by hand
42 // but that would propagate an stl dependency out which we'd rather not
43 // do (see bug 666609). Plus, the entries array is expect to stay small
44 // so doing a realloc everytime we add a new entry shouldn't be too costly
45 entries = static_cast<Entry*>(realloc(entries, sizeof(Entry)*(count+1)));
47 if (!entries) {
48 MOZ_CRASH();
49 }
51 entries[count].key = key;
52 entries[count].userData = userData;
53 entries[count].destroy = destroy;
55 count++;
56 }
58 /* Remove and return user data associated with key, without destroying it */
59 void* Remove(UserDataKey *key)
60 {
61 for (int i=0; i<count; i++) {
62 if (key == entries[i].key) {
63 void *userData = entries[i].userData;
64 // decrement before looping so entries[i+1] doesn't read past the end:
65 --count;
66 for (;i<count; i++) {
67 entries[i] = entries[i+1];
68 }
69 return userData;
70 }
71 }
72 return nullptr;
73 }
75 /* Retrives the userData for the associated key */
76 void *Get(UserDataKey *key) const
77 {
78 for (int i=0; i<count; i++) {
79 if (key == entries[i].key) {
80 return entries[i].userData;
81 }
82 }
83 return nullptr;
84 }
86 bool Has(UserDataKey *key)
87 {
88 for (int i=0; i<count; i++) {
89 if (key == entries[i].key) {
90 return true;
91 }
92 }
93 return false;
94 }
96 void Destroy()
97 {
98 for (int i=0; i<count; i++) {
99 if (entries[i].destroy) {
100 entries[i].destroy(entries[i].userData);
101 }
102 }
103 free(entries);
104 entries = nullptr;
105 count = 0;
106 }
108 ~UserData()
109 {
110 Destroy();
111 }
113 private:
114 struct Entry {
115 const UserDataKey *key;
116 void *userData;
117 destroyFunc destroy;
118 };
120 int count;
121 Entry *entries;
123 };
125 }
126 }
128 #endif /* MOZILLA_GFX_USERDATA_H_ */