1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #include "mozilla/ClearOnShutdown.h"
6 #include "mozilla/StaticPtr.h"
7 #include "mozilla/XULStore.h"
8 #include "nsCOMPtr.h"
9 
10 namespace mozilla {
11 
12 // The XULStore API is implemented in Rust and exposed to C++ via a set of
13 // C functions with the "xulstore_" prefix.  We declare them in this anonymous
14 // namespace to prevent C++ code outside this file from accessing them,
15 // as they are an internal implementation detail, and C++ code should use
16 // the mozilla::XULStore::* functions and mozilla::XULStoreIterator class
17 // declared in XULStore.h.
18 namespace {
19 extern "C" {
20 void xulstore_new_service(nsIXULStore** result);
21 nsresult xulstore_set_value(const nsAString* doc, const nsAString* id,
22                             const nsAString* attr, const nsAString* value);
23 nsresult xulstore_has_value(const nsAString* doc, const nsAString* id,
24                             const nsAString* attr, bool* has_value);
25 nsresult xulstore_get_value(const nsAString* doc, const nsAString* id,
26                             const nsAString* attr, nsAString* value);
27 nsresult xulstore_remove_value(const nsAString* doc, const nsAString* id,
28                                const nsAString* attr);
29 XULStoreIterator* xulstore_get_ids(const nsAString* doc, nsresult* result);
30 XULStoreIterator* xulstore_get_attrs(const nsAString* doc, const nsAString* id,
31                                      nsresult* result);
32 bool xulstore_iter_has_more(const XULStoreIterator*);
33 nsresult xulstore_iter_get_next(XULStoreIterator*, nsAString* value);
34 void xulstore_iter_free(XULStoreIterator* iterator);
35 nsresult xulstore_shutdown();
36 }
37 
38 // A static reference to the nsIXULStore singleton that JS uses to access
39 // the store.  Retrieved via mozilla::XULStore::GetService().
40 static StaticRefPtr<nsIXULStore> sXULStore;
41 }  // namespace
42 
HasMore() const43 bool XULStoreIterator::HasMore() const { return xulstore_iter_has_more(this); }
44 
GetNext(nsAString * item)45 nsresult XULStoreIterator::GetNext(nsAString* item) {
46   return xulstore_iter_get_next(this, item);
47 }
48 
operator ()(XULStoreIterator * ptr) const49 void DefaultDelete<XULStoreIterator>::operator()(XULStoreIterator* ptr) const {
50   xulstore_iter_free(ptr);
51 }
52 
53 namespace XULStore {
GetService()54 already_AddRefed<nsIXULStore> GetService() {
55   nsCOMPtr<nsIXULStore> xulStore;
56 
57   if (sXULStore) {
58     xulStore = sXULStore;
59   } else {
60     xulstore_new_service(getter_AddRefs(xulStore));
61     sXULStore = xulStore;
62     mozilla::ClearOnShutdown(&sXULStore);
63   }
64 
65   return xulStore.forget();
66 }
67 
SetValue(const nsAString & doc,const nsAString & id,const nsAString & attr,const nsAString & value)68 nsresult SetValue(const nsAString& doc, const nsAString& id,
69                   const nsAString& attr, const nsAString& value) {
70   return xulstore_set_value(&doc, &id, &attr, &value);
71 }
HasValue(const nsAString & doc,const nsAString & id,const nsAString & attr,bool & has_value)72 nsresult HasValue(const nsAString& doc, const nsAString& id,
73                   const nsAString& attr, bool& has_value) {
74   return xulstore_has_value(&doc, &id, &attr, &has_value);
75 }
GetValue(const nsAString & doc,const nsAString & id,const nsAString & attr,nsAString & value)76 nsresult GetValue(const nsAString& doc, const nsAString& id,
77                   const nsAString& attr, nsAString& value) {
78   return xulstore_get_value(&doc, &id, &attr, &value);
79 }
RemoveValue(const nsAString & doc,const nsAString & id,const nsAString & attr)80 nsresult RemoveValue(const nsAString& doc, const nsAString& id,
81                      const nsAString& attr) {
82   return xulstore_remove_value(&doc, &id, &attr);
83 }
GetIDs(const nsAString & doc,UniquePtr<XULStoreIterator> & iter)84 nsresult GetIDs(const nsAString& doc, UniquePtr<XULStoreIterator>& iter) {
85   // We assign the value of the iter here in C++ via a return value
86   // rather than in the Rust function via an out parameter in order
87   // to ensure that any old value is deleted, since the UniquePtr's
88   // assignment operator won't delete the old value if the assignment
89   // happens in Rust.
90   nsresult result;
91   iter.reset(xulstore_get_ids(&doc, &result));
92   return result;
93 }
GetAttrs(const nsAString & doc,const nsAString & id,UniquePtr<XULStoreIterator> & iter)94 nsresult GetAttrs(const nsAString& doc, const nsAString& id,
95                   UniquePtr<XULStoreIterator>& iter) {
96   // We assign the value of the iter here in C++ via a return value
97   // rather than in the Rust function via an out parameter in order
98   // to ensure that any old value is deleted, since the UniquePtr's
99   // assignment operator won't delete the old value if the assignment
100   // happens in Rust.
101   nsresult result;
102   iter.reset(xulstore_get_attrs(&doc, &id, &result));
103   return result;
104 }
Shutdown()105 nsresult Shutdown() { return xulstore_shutdown(); }
106 
107 };  // namespace XULStore
108 };  // namespace mozilla
109