OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/geolocation/geolocation_permission_context.h" | 5 #include "chrome/browser/geolocation/geolocation_permission_context.h" |
6 | 6 |
7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
9 #include "base/file_util.h" | 9 #include "googleurl/src/gurl.h" |
10 #include "chrome/browser/browser.h" | 10 #include "chrome/browser/browser.h" |
11 #include "chrome/browser/browser_list.h" | 11 #include "chrome/browser/browser_list.h" |
12 #include "chrome/browser/chrome_thread.h" | 12 #include "chrome/browser/chrome_thread.h" |
13 #include "chrome/browser/geolocation/geolocation_dispatcher_host.h" | 13 #include "chrome/browser/geolocation/geolocation_dispatcher_host.h" |
| 14 #include "chrome/browser/host_content_settings_map.h" |
14 #include "chrome/browser/profile.h" | 15 #include "chrome/browser/profile.h" |
15 #include "chrome/browser/renderer_host/render_process_host.h" | 16 #include "chrome/browser/renderer_host/render_process_host.h" |
16 #include "chrome/browser/renderer_host/render_view_host.h" | 17 #include "chrome/browser/renderer_host/render_view_host.h" |
17 #include "chrome/browser/renderer_host/render_view_host_notification_task.h" | 18 #include "chrome/browser/renderer_host/render_view_host_notification_task.h" |
18 #include "chrome/browser/tab_contents/infobar_delegate.h" | 19 #include "chrome/browser/tab_contents/infobar_delegate.h" |
19 #include "chrome/browser/tab_contents/tab_contents.h" | 20 #include "chrome/browser/tab_contents/tab_contents.h" |
20 #include "chrome/browser/tab_contents/tab_util.h" | 21 #include "chrome/browser/tab_contents/tab_util.h" |
21 #include "chrome/common/json_value_serializer.h" | |
22 #include "chrome/common/render_messages.h" | 22 #include "chrome/common/render_messages.h" |
23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
24 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 const FilePath::CharType kGeolocationPermissionPath[] = | |
29 FILE_PATH_LITERAL("Geolocation"); | |
30 | |
31 const wchar_t kAllowedDictionaryKey[] = L"allowed"; | |
32 | |
33 // This is the delegate used to display the confirmation info bar. | 28 // This is the delegate used to display the confirmation info bar. |
34 class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { | 29 class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { |
35 public: | 30 public: |
36 GeolocationConfirmInfoBarDelegate( | 31 GeolocationConfirmInfoBarDelegate( |
37 TabContents* tab_contents, GeolocationPermissionContext* context, | 32 TabContents* tab_contents, GeolocationPermissionContext* context, |
38 int render_process_id, int render_view_id, int bridge_id, | 33 int render_process_id, int render_view_id, int bridge_id, |
39 const std::string& host) | 34 const std::string& host) |
40 : ConfirmInfoBarDelegate(tab_contents), context_(context), | 35 : ConfirmInfoBarDelegate(tab_contents), context_(context), |
41 render_process_id_(render_process_id), render_view_id_(render_view_id), | 36 render_process_id_(render_process_id), render_view_id_(render_view_id), |
42 bridge_id_(bridge_id), host_(host) { | 37 bridge_id_(bridge_id), host_(host) { |
(...skipping 23 matching lines...) Expand all Loading... |
66 IDS_GEOLOCATION_INFOBAR_QUESTION, UTF8ToWide(host_)); | 61 IDS_GEOLOCATION_INFOBAR_QUESTION, UTF8ToWide(host_)); |
67 } | 62 } |
68 | 63 |
69 virtual SkBitmap* GetIcon() const { | 64 virtual SkBitmap* GetIcon() const { |
70 return ResourceBundle::GetSharedInstance().GetBitmapNamed( | 65 return ResourceBundle::GetSharedInstance().GetBitmapNamed( |
71 IDR_GEOLOCATION_INFOBAR_ICON); | 66 IDR_GEOLOCATION_INFOBAR_ICON); |
72 } | 67 } |
73 | 68 |
74 private: | 69 private: |
75 bool SetPermission(bool confirm) { | 70 bool SetPermission(bool confirm) { |
76 context_->SetPermission( | 71 context_->SetPermissionFromInfobar( |
77 render_process_id_, render_view_id_, bridge_id_, host_, confirm); | 72 render_process_id_, render_view_id_, bridge_id_, host_, confirm); |
78 return true; | 73 return true; |
79 } | 74 } |
80 | 75 |
81 scoped_refptr<GeolocationPermissionContext> context_; | 76 scoped_refptr<GeolocationPermissionContext> context_; |
82 int render_process_id_; | 77 int render_process_id_; |
83 int render_view_id_; | 78 int render_view_id_; |
84 int bridge_id_; | 79 int bridge_id_; |
85 std::string host_; | 80 std::string host_; |
86 }; | 81 }; |
87 | |
88 // TODO(bulach): use HostContentSettingsMap instead! | |
89 FilePath::StringType StdStringToFilePathString(const std::string& std_string) { | |
90 #if defined(OS_WIN) | |
91 return UTF8ToWide(std_string); | |
92 #else | |
93 return std_string; | |
94 #endif | |
95 } | |
96 | |
97 // Returns true if permission was successfully read from file, and *allowed | |
98 // be set accordingly. | |
99 // Returns false otherwise. | |
100 bool ReadPermissionFromFile( | |
101 const std::string& host, const FilePath& permissions_path, bool* allowed) { | |
102 DCHECK(allowed); | |
103 *allowed = false; | |
104 // TODO(bulach): this is probably wrong! is there any utility to convert a URL | |
105 // to FilePath? | |
106 FilePath permission_file( | |
107 permissions_path.Append(StdStringToFilePathString(host))); | |
108 if (!file_util::PathExists(permission_file)) | |
109 return false; | |
110 JSONFileValueSerializer serializer(permission_file); | |
111 scoped_ptr<Value> root_value(serializer.Deserialize(NULL)); | |
112 bool ret = root_value.get() && | |
113 root_value->GetType() == Value::TYPE_DICTIONARY; | |
114 DictionaryValue* dictionary = static_cast<DictionaryValue*>(root_value.get()); | |
115 return ret && | |
116 dictionary->GetBoolean(kAllowedDictionaryKey, allowed); | |
117 } | |
118 | |
119 void SavePermissionToFile( | |
120 const std::string& host, const FilePath& permissions_path, bool allowed) { | |
121 #if 0 | |
122 if (!file_util::DirectoryExists(permissions_path)) | |
123 file_util::CreateDirectory(permissions_path); | |
124 // TODO(bulach): this is probably wrong! is there any utility to convert a URL | |
125 // to FilePath? | |
126 FilePath permission_file( | |
127 permissions_path.Append(StdStringToFilePathString( | |
128 host))); | |
129 DictionaryValue dictionary; | |
130 dictionary.SetBoolean(kAllowedDictionaryKey, allowed); | |
131 std::string permission_data; | |
132 JSONStringValueSerializer serializer(&permission_data); | |
133 serializer.Serialize(dictionary); | |
134 file_util::WriteFile( | |
135 permission_file, permission_data.c_str(), permission_data.length()); | |
136 #endif // if 0 | |
137 } | |
138 | |
139 } // namespace | 82 } // namespace |
140 | 83 |
141 GeolocationPermissionContext::GeolocationPermissionContext( | 84 GeolocationPermissionContext::GeolocationPermissionContext( |
142 Profile* profile) | 85 HostContentSettingsMap* host_content_settings_map) |
143 : profile_(profile), | 86 : host_content_settings_map_(host_content_settings_map) { |
144 is_off_the_record_(profile->IsOffTheRecord()), | 87 DCHECK(host_content_settings_map_); |
145 permissions_path_(profile->GetPath().Append(FilePath( | |
146 kGeolocationPermissionPath))) { | |
147 } | 88 } |
148 | 89 |
149 GeolocationPermissionContext::~GeolocationPermissionContext() { | 90 GeolocationPermissionContext::~GeolocationPermissionContext() { |
150 } | 91 } |
151 | 92 |
152 void GeolocationPermissionContext::RequestGeolocationPermission( | 93 void GeolocationPermissionContext::RequestGeolocationPermission( |
153 int render_process_id, int render_view_id, int bridge_id, | 94 int render_process_id, int render_view_id, int bridge_id, |
154 const std::string& host) { | 95 const std::string& host) { |
155 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 96 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
156 std::map<std::string, bool>::const_iterator permission = | 97 ContentSetting content_setting = |
157 permissions_.find(host); | 98 host_content_settings_map_->GetContentSetting( |
158 if (permission != permissions_.end()) { | 99 host, CONTENT_SETTINGS_TYPE_GEOLOCATION); |
159 NotifyPermissionSet( | 100 if (content_setting == CONTENT_SETTING_ASK) { |
160 render_process_id, render_view_id, bridge_id, permission->second); | 101 RequestPermissionFromUI(render_process_id, render_view_id, bridge_id, host); |
| 102 } else if (content_setting == CONTENT_SETTING_ALLOW) { |
| 103 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, host, |
| 104 true); |
| 105 } else if (content_setting == CONTENT_SETTING_BLOCK) { |
| 106 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, host, |
| 107 false); |
161 } else { | 108 } else { |
162 HandlePermissionMemoryCacheMiss( | 109 NOTREACHED() << "unknown content setting" << content_setting; |
163 render_process_id, render_view_id, bridge_id, host); | |
164 } | 110 } |
165 } | 111 } |
166 | 112 |
167 void GeolocationPermissionContext::SetPermission( | 113 void GeolocationPermissionContext::SetPermissionFromInfobar( |
168 int render_process_id, int render_view_id, int bridge_id, | 114 int render_process_id, int render_view_id, int bridge_id, |
169 const std::string& host, bool allowed) { | 115 const std::string& host, bool allowed) { |
170 SetPermissionMemoryCacheOnIOThread(host, allowed); | 116 host_content_settings_map_->SetContentSetting( |
171 SetPermissionOnFileThread(host, allowed); | 117 host, CONTENT_SETTINGS_TYPE_GEOLOCATION, |
172 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, allowed); | 118 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); |
| 119 NotifyPermissionSet( |
| 120 render_process_id, render_view_id, bridge_id, host, allowed); |
173 } | 121 } |
174 | 122 |
175 void GeolocationPermissionContext::HandlePermissionMemoryCacheMiss( | 123 void GeolocationPermissionContext::SetPermissionFromContentBubble( |
176 int render_process_id, int render_view_id, int bridge_id, | 124 TabContents* tab_contents, const std::string& host, bool allowed) { |
177 const std::string& host) { | 125 int render_process_id = tab_contents->render_view_host()->process()->id(); |
178 if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) { | 126 int render_view_id = tab_contents->render_view_host()->routing_id(); |
179 ChromeThread::PostTask( | 127 host_content_settings_map_->SetContentSetting( |
180 ChromeThread::FILE, FROM_HERE, | 128 host, CONTENT_SETTINGS_TYPE_GEOLOCATION, |
181 NewRunnableMethod( | 129 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); |
182 this, | 130 RenderViewHostDelegate::Resource* resource = tab_util::GetTabContentsByID( |
183 &GeolocationPermissionContext::HandlePermissionMemoryCacheMiss, | 131 render_process_id, render_view_id); |
184 render_process_id, render_view_id, bridge_id, host)); | 132 resource->OnGeolocationPermissionSet(host, allowed); |
185 return; | 133 // TODO(bulach): should we traverse all registered bridges? JS callbacks will |
186 } | 134 // have already been triggered at this point, so they have already received |
187 | 135 // their position updated or error callbacks. |
188 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | |
189 // TODO(bulach): should we save a file per host or have some smarter | |
190 // storage? Use HostContentSettingsMap instead. | |
191 bool allowed; | |
192 if (is_off_the_record_ || | |
193 !ReadPermissionFromFile(host, permissions_path_, &allowed)) { | |
194 RequestPermissionFromUI( | |
195 render_process_id, render_view_id, bridge_id, host); | |
196 } else { | |
197 SetPermissionMemoryCacheOnIOThread(host, allowed); | |
198 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, allowed); | |
199 } | |
200 } | 136 } |
201 | 137 |
202 void GeolocationPermissionContext::RequestPermissionFromUI( | 138 void GeolocationPermissionContext::RequestPermissionFromUI( |
203 int render_process_id, int render_view_id, int bridge_id, | 139 int render_process_id, int render_view_id, int bridge_id, |
204 const std::string& host) { | 140 const std::string& host) { |
205 if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { | 141 if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { |
206 ChromeThread::PostTask( | 142 ChromeThread::PostTask( |
207 ChromeThread::UI, FROM_HERE, | 143 ChromeThread::UI, FROM_HERE, |
208 NewRunnableMethod( | 144 NewRunnableMethod( |
209 this, &GeolocationPermissionContext::RequestPermissionFromUI, | 145 this, &GeolocationPermissionContext::RequestPermissionFromUI, |
210 render_process_id, render_view_id, bridge_id, host)); | 146 render_process_id, render_view_id, bridge_id, host)); |
211 return; | 147 return; |
212 } | 148 } |
213 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 149 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
214 | 150 |
215 TabContents* tab_contents = | 151 TabContents* tab_contents = |
216 tab_util::GetTabContentsByID(render_process_id, render_view_id); | 152 tab_util::GetTabContentsByID(render_process_id, render_view_id); |
217 if (!tab_contents) { | 153 if (!tab_contents) { |
218 // The tab may have gone away, or the request may not be from a tab at all. | 154 // The tab may have gone away, or the request may not be from a tab at all. |
219 LOG(WARNING) << "Attempt to use geolocaiton tabless renderer: " | 155 LOG(WARNING) << "Attempt to use geolocaiton tabless renderer: " |
220 << render_process_id << "," << render_view_id << "," << bridge_id | 156 << render_process_id << "," << render_view_id << "," << bridge_id |
221 << " (geolocation is not supported in extensions)"; | 157 << " (geolocation is not supported in extensions)"; |
222 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, false); | 158 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, host, |
| 159 false); |
223 return; | 160 return; |
224 } | 161 } |
225 tab_contents->AddInfoBar( | 162 tab_contents->AddInfoBar( |
226 new GeolocationConfirmInfoBarDelegate( | 163 new GeolocationConfirmInfoBarDelegate( |
227 tab_contents, this, render_process_id, render_view_id, | 164 tab_contents, this, render_process_id, render_view_id, |
228 bridge_id, host)); | 165 bridge_id, host)); |
229 } | 166 } |
230 | 167 |
231 void GeolocationPermissionContext::NotifyPermissionSet( | 168 void GeolocationPermissionContext::NotifyPermissionSet( |
232 int render_process_id, int render_view_id, int bridge_id, bool allowed) { | 169 int render_process_id, int render_view_id, int bridge_id, |
| 170 const std::string& host, bool allowed) { |
233 if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { | 171 if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { |
234 ChromeThread::PostTask( | 172 ChromeThread::PostTask( |
235 ChromeThread::UI, FROM_HERE, | 173 ChromeThread::UI, FROM_HERE, |
236 NewRunnableMethod( | 174 NewRunnableMethod( |
237 this, &GeolocationPermissionContext::NotifyPermissionSet, | 175 this, &GeolocationPermissionContext::NotifyPermissionSet, |
238 render_process_id, render_view_id, bridge_id, allowed)); | 176 render_process_id, render_view_id, bridge_id, |
| 177 host, allowed)); |
239 return; | 178 return; |
240 } | 179 } |
241 | 180 |
242 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 181 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 182 |
| 183 RenderViewHostDelegate::Resource* resource = tab_util::GetTabContentsByID( |
| 184 render_process_id, render_view_id); |
| 185 resource->OnGeolocationPermissionSet(host, allowed); |
243 CallRenderViewHost( | 186 CallRenderViewHost( |
244 render_process_id, render_view_id, | 187 render_process_id, render_view_id, |
245 &RenderViewHost::Send, | 188 &RenderViewHost::Send, |
246 new ViewMsg_Geolocation_PermissionSet( | 189 new ViewMsg_Geolocation_PermissionSet( |
247 render_view_id, bridge_id, allowed)); | 190 render_view_id, bridge_id, allowed)); |
248 } | 191 } |
249 | |
250 void GeolocationPermissionContext::SetPermissionMemoryCacheOnIOThread( | |
251 const std::string& host, bool allowed) { | |
252 if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { | |
253 ChromeThread::PostTask( | |
254 ChromeThread::IO, FROM_HERE, | |
255 NewRunnableMethod( | |
256 this, | |
257 &GeolocationPermissionContext::SetPermissionMemoryCacheOnIOThread, | |
258 host, allowed)); | |
259 return; | |
260 } | |
261 | |
262 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | |
263 permissions_[host] = allowed; | |
264 } | |
265 | |
266 void GeolocationPermissionContext::SetPermissionOnFileThread( | |
267 const std::string& host, bool allowed) { | |
268 if (is_off_the_record_) | |
269 return; | |
270 if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) { | |
271 ChromeThread::PostTask( | |
272 ChromeThread::FILE, FROM_HERE, | |
273 NewRunnableMethod( | |
274 this, &GeolocationPermissionContext::SetPermissionOnFileThread, | |
275 host, allowed)); | |
276 return; | |
277 } | |
278 | |
279 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | |
280 | |
281 // TODO(bulach): should we save a file per host or have some smarter | |
282 // storage? Use HostContentSettingsMap instead. | |
283 #if 0 | |
284 SavePermissionToFile(host, permissions_path_, allowed); | |
285 #endif | |
286 } | |
OLD | NEW |