1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Indexed Database.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * The Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2010
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Ben Turner <bent.mozilla@gmail.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "CheckPermissionsHelper.h"
41 :
42 : #include "nsIDOMWindow.h"
43 : #include "nsIObserverService.h"
44 : #include "nsIPermissionManager.h"
45 : #include "nsIPrincipal.h"
46 : #include "nsIScriptObjectPrincipal.h"
47 : #include "nsIURI.h"
48 :
49 : #include "nsContentUtils.h"
50 : #include "nsDOMStorage.h"
51 : #include "nsNetUtil.h"
52 : #include "nsThreadUtils.h"
53 : #include "mozilla/Services.h"
54 : #include "mozilla/Preferences.h"
55 :
56 : #include "IndexedDatabaseManager.h"
57 :
58 : #define PERMISSION_INDEXEDDB "indexedDB"
59 : #define PREF_INDEXEDDB_ENABLED "dom.indexedDB.enabled"
60 : #define TOPIC_PERMISSIONS_PROMPT "indexedDB-permissions-prompt"
61 : #define TOPIC_PERMISSIONS_RESPONSE "indexedDB-permissions-response"
62 :
63 : using namespace mozilla;
64 : USING_INDEXEDDB_NAMESPACE
65 : using namespace mozilla::services;
66 :
67 : namespace {
68 :
69 : inline
70 : PRUint32
71 76 : GetIndexedDBPermissions(const nsACString& aASCIIOrigin,
72 : nsIDOMWindow* aWindow)
73 : {
74 76 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
75 :
76 76 : if (!Preferences::GetBool(PREF_INDEXEDDB_ENABLED)) {
77 0 : return nsIPermissionManager::DENY_ACTION;
78 : }
79 :
80 : // No window here means chrome access
81 76 : if (!aWindow) {
82 76 : return nsIPermissionManager::ALLOW_ACTION;
83 : }
84 :
85 0 : nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(aWindow));
86 0 : NS_ENSURE_TRUE(sop, nsIPermissionManager::DENY_ACTION);
87 :
88 0 : if (nsContentUtils::IsSystemPrincipal(sop->GetPrincipal())) {
89 0 : return nsIPermissionManager::ALLOW_ACTION;
90 : }
91 :
92 0 : if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) {
93 : // TODO Support private browsing indexedDB?
94 0 : return nsIPermissionManager::DENY_ACTION;
95 : }
96 :
97 0 : nsCOMPtr<nsIURI> uri;
98 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), aASCIIOrigin);
99 0 : NS_ENSURE_SUCCESS(rv, nsIPermissionManager::DENY_ACTION);
100 :
101 : nsCOMPtr<nsIPermissionManager> permissionManager =
102 0 : do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
103 0 : NS_ENSURE_TRUE(permissionManager, nsIPermissionManager::DENY_ACTION);
104 :
105 : PRUint32 permission;
106 0 : rv = permissionManager->TestPermission(uri, PERMISSION_INDEXEDDB,
107 0 : &permission);
108 0 : NS_ENSURE_SUCCESS(rv, nsIPermissionManager::DENY_ACTION);
109 :
110 0 : return permission;
111 : }
112 :
113 : } // anonymous namespace
114 :
115 723 : NS_IMPL_THREADSAFE_ISUPPORTS3(CheckPermissionsHelper, nsIRunnable,
116 : nsIInterfaceRequestor,
117 : nsIObserver)
118 :
119 : NS_IMETHODIMP
120 76 : CheckPermissionsHelper::Run()
121 : {
122 76 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
123 :
124 : PRUint32 permission = mHasPrompted ?
125 : mPromptResult :
126 76 : GetIndexedDBPermissions(mASCIIOrigin, mWindow);
127 :
128 : nsresult rv;
129 76 : if (mHasPrompted) {
130 : // Add permissions to the database, but only if we are in the parent
131 : // process (if we are in the child process, we have already
132 : // set the permission when the prompt was shown in the parent, as
133 : // we cannot set the permission from the child).
134 0 : if (permission != nsIPermissionManager::UNKNOWN_ACTION &&
135 0 : XRE_GetProcessType() == GeckoProcessType_Default) {
136 0 : nsCOMPtr<nsIURI> uri;
137 0 : rv = NS_NewURI(getter_AddRefs(uri), mASCIIOrigin);
138 0 : NS_ENSURE_SUCCESS(rv, rv);
139 :
140 : nsCOMPtr<nsIPermissionManager> permissionManager =
141 0 : do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
142 0 : NS_ENSURE_STATE(permissionManager);
143 :
144 0 : rv = permissionManager->Add(uri, PERMISSION_INDEXEDDB, permission,
145 0 : nsIPermissionManager::EXPIRE_NEVER, 0);
146 0 : NS_ENSURE_SUCCESS(rv, rv);
147 : }
148 : }
149 76 : else if (permission == nsIPermissionManager::UNKNOWN_ACTION &&
150 : mPromptAllowed) {
151 0 : nsCOMPtr<nsIObserverService> obs = GetObserverService();
152 0 : rv = obs->NotifyObservers(static_cast<nsIRunnable*>(this),
153 0 : TOPIC_PERMISSIONS_PROMPT, nsnull);
154 0 : NS_ENSURE_SUCCESS(rv, rv);
155 :
156 0 : return NS_OK;
157 : }
158 :
159 152 : nsRefPtr<OpenDatabaseHelper> helper;
160 76 : helper.swap(mHelper);
161 :
162 152 : nsCOMPtr<nsIDOMWindow> window;
163 76 : window.swap(mWindow);
164 :
165 76 : if (permission == nsIPermissionManager::ALLOW_ACTION) {
166 76 : IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
167 76 : NS_ASSERTION(mgr, "This should never be null!");
168 :
169 76 : return helper->Dispatch(mgr->IOThread());
170 : }
171 :
172 0 : NS_ASSERTION(permission == nsIPermissionManager::UNKNOWN_ACTION ||
173 : permission == nsIPermissionManager::DENY_ACTION,
174 : "Unknown permission!");
175 :
176 0 : helper->SetError(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
177 :
178 0 : return helper->RunImmediately();
179 : }
180 :
181 : NS_IMETHODIMP
182 0 : CheckPermissionsHelper::GetInterface(const nsIID& aIID,
183 : void** aResult)
184 : {
185 0 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
186 0 : if (aIID.Equals(NS_GET_IID(nsIObserver))) {
187 0 : return QueryInterface(aIID, aResult);
188 : }
189 :
190 0 : if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
191 0 : return mWindow->QueryInterface(aIID, aResult);
192 : }
193 :
194 0 : *aResult = nsnull;
195 0 : return NS_ERROR_NOT_AVAILABLE;
196 : }
197 :
198 : NS_IMETHODIMP
199 0 : CheckPermissionsHelper::Observe(nsISupports* aSubject,
200 : const char* aTopic,
201 : const PRUnichar* aData)
202 : {
203 0 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
204 0 : NS_ASSERTION(!strcmp(aTopic, TOPIC_PERMISSIONS_RESPONSE), "Bad topic!");
205 0 : NS_ASSERTION(mPromptAllowed, "How did we get here?");
206 :
207 0 : mHasPrompted = true;
208 :
209 : nsresult rv;
210 0 : mPromptResult = nsDependentString(aData).ToInteger(&rv);
211 0 : NS_ENSURE_SUCCESS(rv, rv);
212 :
213 0 : rv = NS_DispatchToCurrentThread(this);
214 0 : NS_ENSURE_SUCCESS(rv, rv);
215 :
216 0 : return NS_OK;
217 : }
|