blob: 8d891fa1e9bf643712f3d66413ac5447b9ad633c [file] [log] [blame]
Tarun Bansal0b8b7afd2017-08-25 03:52:161// Copyright 2017 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/client_hints/client_hints_observer.h"
6
7#include <memory>
8
9#include "base/metrics/histogram_macros.h"
10#include "base/values.h"
Tarun Bansala61f0f62017-10-24 23:53:0511#include "chrome/browser/content_settings/cookie_settings_factory.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1612#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
13#include "chrome/browser/profiles/profile.h"
Tarun Bansala61f0f62017-10-24 23:53:0514#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1615#include "components/content_settings/core/browser/host_content_settings_map.h"
16#include "components/content_settings/core/common/content_settings_pattern.h"
17#include "components/content_settings/core/common/content_settings_types.h"
18#include "content/public/browser/browser_context.h"
19#include "content/public/browser/browser_thread.h"
20#include "content/public/browser/render_frame_host.h"
21#include "content/public/browser/render_process_host.h"
22#include "content/public/browser/web_contents.h"
23#include "content/public/common/origin_util.h"
24#include "url/gurl.h"
25#include "url/origin.h"
26
27ClientHintsObserver::ClientHintsObserver(content::WebContents* tab)
28 : binding_(tab, this) {}
29
30ClientHintsObserver::~ClientHintsObserver() {}
31
32void ClientHintsObserver::PersistClientHints(
33 const url::Origin& primary_origin,
34 const std::vector<::blink::mojom::WebClientHintsType>& client_hints,
35 base::TimeDelta expiration_duration) {
36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
37
38 const GURL primary_url = primary_origin.GetURL();
39
40 // TODO(tbansal): crbug.com/735518. Consider killing the renderer that sent
41 // the malformed IPC.
42 if (!primary_url.is_valid() || !content::IsOriginSecure(primary_url))
43 return;
44
Tarun Bansal10fd90d2018-03-14 00:32:2845 DCHECK(!client_hints.empty());
Daniel Chengcda1df5b2018-03-30 21:30:1646 DCHECK_LE(
47 client_hints.size(),
48 static_cast<size_t>(blink::mojom::WebClientHintsType::kMaxValue) + 1);
Tarun Bansal10fd90d2018-03-14 00:32:2849
Tarun Bansal0b8b7afd2017-08-25 03:52:1650 if (client_hints.empty() ||
51 client_hints.size() >
Daniel Chengcda1df5b2018-03-30 21:30:1652 (static_cast<size_t>(blink::mojom::WebClientHintsType::kMaxValue) +
53 1)) {
Tarun Bansal0b8b7afd2017-08-25 03:52:1654 // Return early if the list does not have the right number of values.
55 // Persisting wrong number of values to the disk may cause errors when
56 // reading them back in the future.
57 return;
58 }
59
60 if (expiration_duration <= base::TimeDelta::FromSeconds(0))
61 return;
62
63 content::RenderProcessHost* rph =
64 binding_.GetCurrentTargetFrame()->GetProcess();
65 content::BrowserContext* browser_context = rph->GetBrowserContext();
66 Profile* profile = Profile::FromBrowserContext(browser_context);
67
Tarun Bansala61f0f62017-10-24 23:53:0568 scoped_refptr<content_settings::CookieSettings> cookie_settings =
69 CookieSettingsFactory::GetForProfile(profile);
70 if (!cookie_settings->IsCookieAccessAllowed(primary_url, primary_url)) {
71 // If |primary_url| is disallowed from storing cookies, then |primary_url|
72 // is also prevented from storing client hints.
73 return;
74 }
75
Tarun Bansal0b8b7afd2017-08-25 03:52:1676 HostContentSettingsMap* map =
77 HostContentSettingsMapFactory::GetForProfile(profile);
78
79 std::unique_ptr<base::ListValue> expiration_times_list =
Jeremy Romanec48d7a2018-03-01 17:35:0980 std::make_unique<base::ListValue>();
Tarun Bansal0b8b7afd2017-08-25 03:52:1681 expiration_times_list->Reserve(client_hints.size());
82
83 // Use wall clock since the expiration time would be persisted across embedder
84 // restarts.
85 double expiration_time =
86 (base::Time::Now() + expiration_duration).ToDoubleT();
87
88 for (const auto& entry : client_hints)
89 expiration_times_list->AppendInteger(static_cast<int>(entry));
90
91 auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
92 expiration_times_dictionary->SetList("client_hints",
93 std::move(expiration_times_list));
94 expiration_times_dictionary->SetDouble("expiration_time", expiration_time);
95
96 // TODO(tbansal): crbug.com/735518. Disable updates to client hints settings
97 // when cookies are disabled for |primary_origin|.
98 map->SetWebsiteSettingDefaultScope(
99 primary_url, GURL(), CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
100 std::move(expiration_times_dictionary));
101
102 UMA_HISTOGRAM_EXACT_LINEAR("ClientHints.UpdateEventCount", 1, 2);
103}
104
105DEFINE_WEB_CONTENTS_USER_DATA_KEY(ClientHintsObserver);