Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / transition_request_manager.cc
blob680c2d4c4eb66eb810f3889bb14288aa825d757a
1 // Copyright 2014 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.
5 #include "content/browser/transition_request_manager.h"
7 #include "base/command_line.h"
8 #include "base/memory/singleton.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/strings/string_util.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/common/content_switches.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/http/http_util.h"
16 namespace {
18 // Enumerate all Link: headers with the specified relation in this
19 // response, and optionally returns the URL and any additional attributes of
20 // each one. See EnumerateHeaders for |iter| usage.
21 bool EnumerateLinkHeaders(
22 const scoped_refptr<net::HttpResponseHeaders>& headers,
23 void** iter,
24 const std::string& rel,
25 std::string* url,
26 std::vector<std::pair<std::string, std::string> >* attributes) {
27 std::string header_body;
28 bool rel_matched = false;
29 while (!rel_matched && headers->EnumerateHeader(iter, "link", &header_body)) {
30 const std::string::const_iterator begin = header_body.begin();
31 size_t url_start = header_body.find_first_of('<');
32 size_t url_end = header_body.find_first_of('>');
33 if (url_start == std::string::npos || url_end == std::string::npos ||
34 url_start > url_end) {
35 break;
38 if (attributes)
39 attributes->clear();
41 net::HttpUtil::NameValuePairsIterator param_iter(
42 begin + url_end + 1, header_body.end(), ';');
44 while (param_iter.GetNext()) {
45 if (LowerCaseEqualsASCII(
46 param_iter.name_begin(), param_iter.name_end(), "rel")) {
47 if (LowerCaseEqualsASCII(param_iter.value_begin(),
48 param_iter.value_end(),
49 rel.c_str())) {
50 if (url) {
51 url->assign(begin + url_start + 1, begin + url_end);
53 rel_matched = true;
54 } else {
55 break;
57 } else if (attributes) {
58 std::string attribute_name(param_iter.name_begin(),
59 param_iter.name_end());
60 std::string attribute_value(param_iter.value_begin(),
61 param_iter.value_end());
62 attributes->push_back(std::make_pair(attribute_name, attribute_value));
67 if (!rel_matched && attributes) {
68 attributes->clear();
71 return rel_matched;
74 } // namespace
76 namespace content {
78 TransitionLayerData::TransitionLayerData() {
81 TransitionLayerData::~TransitionLayerData() {
84 void TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
85 const scoped_refptr<net::HttpResponseHeaders>& headers,
86 std::vector<GURL>& entering_stylesheets,
87 const GURL& resolve_address) {
88 if (headers.get() == NULL)
89 return;
91 std::string transition_stylesheet;
92 std::vector<std::pair<std::string, std::string> > attributes;
93 void* header_iter = NULL;
94 while (EnumerateLinkHeaders(headers,
95 &header_iter,
96 "transition-entering-stylesheet",
97 &transition_stylesheet,
98 &attributes)) {
99 GURL stylesheet_url = resolve_address.Resolve(transition_stylesheet);
100 if (stylesheet_url.is_valid())
101 entering_stylesheets.push_back(stylesheet_url);
105 TransitionRequestManager::TransitionRequestData::TransitionRequestData() {
108 TransitionRequestManager::TransitionRequestData::~TransitionRequestData() {
111 void TransitionRequestManager::TransitionRequestData::AddEntry(
112 const std::string& allowed_destination_host_pattern,
113 const std::string& css_selector,
114 const std::string& markup) {
115 allowed_entries_.push_back(AllowedEntry(allowed_destination_host_pattern,
116 css_selector,
117 markup));
120 bool TransitionRequestManager::TransitionRequestData::FindEntry(
121 const GURL& request_url,
122 TransitionLayerData* transition_data) {
123 DCHECK(!allowed_entries_.empty());
124 CHECK(transition_data);
125 // TODO(oysteine): Add CSP check to validate the host pattern and the
126 // request_url. Must be done before this feature is moved out from the flag.
127 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
128 switches::kEnableExperimentalWebPlatformFeatures) ||
129 base::FieldTrialList::FindFullName("NavigationTransitions") ==
130 "Enabled");
132 const AllowedEntry& allowed_entry = allowed_entries_[0];
133 transition_data->markup = allowed_entry.markup;
134 transition_data->css_selector = allowed_entry.css_selector;
135 return true;
138 bool TransitionRequestManager::HasPendingTransitionRequest(
139 int render_process_id,
140 int render_frame_id,
141 const GURL& request_url,
142 TransitionLayerData* transition_data) {
143 DCHECK_CURRENTLY_ON(BrowserThread::IO);
144 DCHECK(transition_data);
145 std::pair<int, int> key(render_process_id, render_frame_id);
146 RenderFrameRequestDataMap::iterator iter =
147 pending_transition_frames_.find(key);
148 return iter != pending_transition_frames_.end() &&
149 iter->second.FindEntry(request_url, transition_data);
152 void TransitionRequestManager::AddPendingTransitionRequestData(
153 int render_process_id,
154 int render_frame_id,
155 const std::string& allowed_destination_host_pattern,
156 const std::string& css_selector,
157 const std::string& markup) {
158 DCHECK_CURRENTLY_ON(BrowserThread::IO);
160 std::pair<int, int> key(render_process_id, render_frame_id);
161 pending_transition_frames_[key].AddEntry(allowed_destination_host_pattern,
162 css_selector,
163 markup);
166 void TransitionRequestManager::ClearPendingTransitionRequestData(
167 int render_process_id, int render_frame_id) {
168 DCHECK_CURRENTLY_ON(BrowserThread::IO);
169 std::pair<int, int> key(render_process_id, render_frame_id);
170 pending_transition_frames_.erase(key);
173 TransitionRequestManager::TransitionRequestManager() {
176 TransitionRequestManager::~TransitionRequestManager() {
179 // static
180 TransitionRequestManager* TransitionRequestManager::GetInstance() {
181 return Singleton<TransitionRequestManager>::get();
184 } // namespace content