| 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 |