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
3// found in the LICENSE file.
4
5#include "chrome/browser/geolocation/geolocation_settings_state.h"
6
7#include "base/string_piece.h"
8#include "base/utf_string_conversions.h"
9#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
10#include "chrome/browser/prefs/pref_service.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/common/pref_names.h"
13#include "content/browser/tab_contents/navigation_entry.h"
14#include "net/base/net_util.h"
15
16GeolocationSettingsState::GeolocationSettingsState(Profile* profile)
17  : profile_(profile) {
18}
19
20GeolocationSettingsState::~GeolocationSettingsState() {
21}
22
23void GeolocationSettingsState::OnGeolocationPermissionSet(
24    const GURL& requesting_origin, bool allowed) {
25  state_map_[requesting_origin] =
26      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
27}
28
29void GeolocationSettingsState::DidNavigate(
30    const NavigationController::LoadCommittedDetails& details) {
31  if (details.entry)
32    embedder_url_ = details.entry->url();
33  if (state_map_.empty())
34    return;
35  if (!details.entry ||
36      details.previous_url.GetOrigin() != details.entry->url().GetOrigin()) {
37    state_map_.clear();
38    return;
39  }
40  // We're in the same origin, check if there's any icon to be displayed.
41  unsigned int tab_state_flags = 0;
42  GetDetailedInfo(NULL, &tab_state_flags);
43  if (!(tab_state_flags & TABSTATE_HAS_ANY_ICON))
44    state_map_.clear();
45}
46
47void GeolocationSettingsState::ClearStateMap() {
48  state_map_.clear();
49}
50
51void GeolocationSettingsState::GetDetailedInfo(
52    FormattedHostsPerState* formatted_hosts_per_state,
53    unsigned int* tab_state_flags) const {
54  DCHECK(tab_state_flags);
55  DCHECK(embedder_url_.is_valid());
56  const ContentSetting default_setting =
57      profile_->GetGeolocationContentSettingsMap()->GetDefaultContentSetting();
58  std::set<std::string> formatted_hosts;
59  std::set<std::string> repeated_formatted_hosts;
60
61  // Build a set of repeated formatted hosts
62  for (StateMap::const_iterator i(state_map_.begin());
63       i != state_map_.end(); ++i) {
64    std::string formatted_host = GURLToFormattedHost(i->first);
65    if (!formatted_hosts.insert(formatted_host).second) {
66      repeated_formatted_hosts.insert(formatted_host);
67    }
68  }
69
70  for (StateMap::const_iterator i(state_map_.begin());
71       i != state_map_.end(); ++i) {
72    if (i->second == CONTENT_SETTING_ALLOW)
73      *tab_state_flags |= TABSTATE_HAS_ANY_ALLOWED;
74    if (formatted_hosts_per_state) {
75      std::string formatted_host = GURLToFormattedHost(i->first);
76      std::string final_formatted_host =
77          repeated_formatted_hosts.find(formatted_host) ==
78          repeated_formatted_hosts.end() ?
79          formatted_host :
80          i->first.spec();
81      (*formatted_hosts_per_state)[i->second].insert(final_formatted_host);
82    }
83
84    const ContentSetting saved_setting =
85        profile_->GetGeolocationContentSettingsMap()->GetContentSetting(
86            i->first, embedder_url_);
87    if (saved_setting != default_setting)
88      *tab_state_flags |= TABSTATE_HAS_EXCEPTION;
89    if (saved_setting != i->second)
90      *tab_state_flags |= TABSTATE_HAS_CHANGED;
91    if (saved_setting != CONTENT_SETTING_ASK)
92      *tab_state_flags |= TABSTATE_HAS_ANY_ICON;
93  }
94}
95
96std::string GeolocationSettingsState::GURLToFormattedHost(
97    const GURL& url) const {
98  std::wstring display_host_wide;
99  net::AppendFormattedHost(
100      url, UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
101      &display_host_wide, NULL, NULL);
102  return WideToUTF8(display_host_wide);
103}
104