File: content_lofi_decider.cc

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (200 lines) | stat: -rw-r--r-- 7,753 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/data_reduction_proxy/content/browser/content_lofi_decider.h"

#include <string>

#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/resource_type.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request.h"

namespace data_reduction_proxy {

ContentLoFiDecider::ContentLoFiDecider() {}

ContentLoFiDecider::~ContentLoFiDecider() {}

bool ContentLoFiDecider::IsUsingLoFiMode(const net::URLRequest& request) const {
  const content::ResourceRequestInfo* request_info =
      content::ResourceRequestInfo::ForRequest(&request);
  // The Lo-Fi directive should not be added for users in the Lo-Fi field
  // trial "Control" group. Check that the user is in a group that can get
  // "q=low".
  bool lofi_enabled_via_flag_or_field_trial =
      params::IsLoFiOnViaFlags() || params::IsIncludedInLoFiEnabledFieldTrial();

  // Return if the user is using Lo-Fi and not part of the "Control" group.
  if (request_info) {
    return (request_info->GetPreviewsState() & content::SERVER_LOFI_ON) &&
           lofi_enabled_via_flag_or_field_trial;
  }
  return false;
}

void ContentLoFiDecider::MaybeSetAcceptTransformHeader(
    const net::URLRequest& request,
    bool is_previews_disabled,
    net::HttpRequestHeaders* headers) const {
  const content::ResourceRequestInfo* request_info =
      content::ResourceRequestInfo::ForRequest(&request);

  if (!request_info)
    return;

  // Previews only operate on HTTP.
  if (!request.url().SchemeIs("http"))
    return;

  // Chrome-Proxy-Accept-Transform takes at most one token.
  if (headers->HasHeader(chrome_proxy_accept_transform_header()))
    return;

  content::ResourceType resource_type = request_info->GetResourceType();

  if (resource_type == content::RESOURCE_TYPE_MEDIA) {
    headers->SetHeader(chrome_proxy_accept_transform_header(),
                       compressed_video_directive());
    return;
  }

  // The Lo-Fi and Lite Page directives should not be added for users in the
  // Lo-Fi field trial "Control" group.
  bool lofi_enabled_via_flags_or_field_trial =
      params::IsLoFiOnViaFlags() || params::IsIncludedInLoFiEnabledFieldTrial();

  bool lite_page_enabled_via_flags_or_field_trial =
      (params::IsLoFiOnViaFlags() && params::AreLitePagesEnabledViaFlags()) ||
      params::IsIncludedInLitePageFieldTrial();

  // User does not have previews enabled.
  if (!lofi_enabled_via_flags_or_field_trial &&
      !lite_page_enabled_via_flags_or_field_trial) {
    return;
  }

  // Previews has been disabled.
  if (is_previews_disabled)
    return;

  // Do not add the Chrome-Proxy-Accept-Transform header when the page load
  // explicitly forbids previews transformations.
  if (request_info->GetPreviewsState() & content::PREVIEWS_NO_TRANSFORM)
    return;

  // LoFi is not allowed on the main frame, stylesheet, script, font resource,
  // media, service worker, or CSP report.
  bool resource_type_supports_empty_image =
      !(resource_type == content::RESOURCE_TYPE_MAIN_FRAME ||
        resource_type == content::RESOURCE_TYPE_STYLESHEET ||
        resource_type == content::RESOURCE_TYPE_SCRIPT ||
        resource_type == content::RESOURCE_TYPE_FONT_RESOURCE ||
        resource_type == content::RESOURCE_TYPE_MEDIA ||
        resource_type == content::RESOURCE_TYPE_CSP_REPORT);

  // If in the lite page field trial or the lite page flag is enabled, only add
  // the "lite-page" directive on main frame requests. Do not add "empty-image"
  // directives to other requests when Lite Page previews are enabled.
  // Add the "if-heavy" qualifier to allow the server to provide a preview when
  // the page is data heavy on if a preview was not otherwise triggered.
  std::string accept_transform_value;
  if (lite_page_enabled_via_flags_or_field_trial) {
    if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
      accept_transform_value = lite_page_directive();
  } else if (lofi_enabled_via_flags_or_field_trial) {
    if (resource_type_supports_empty_image)
      accept_transform_value = empty_image_directive();
  }
  if (accept_transform_value.empty())
    return;

  if (!(request_info->GetPreviewsState() & content::SERVER_LOFI_ON))
    accept_transform_value += base::StringPrintf(";%s", if_heavy_qualifier());

  headers->SetHeader(chrome_proxy_accept_transform_header(),
                     accept_transform_value);
}

bool ContentLoFiDecider::IsSlowPagePreviewRequested(
    const net::HttpRequestHeaders& headers) const {
  std::string accept_transform_header_value;
  if (!headers.GetHeader(chrome_proxy_accept_transform_header(),
                         &accept_transform_header_value)) {
    return false;
  }

  std::vector<std::string> tokens =
      base::SplitString(base::ToLowerASCII(accept_transform_header_value), ";",
                        base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  // A slow page preview is a request for any unqualified transform type.
  if (tokens.size() != 1)
    return false;
  std::string transform_type;
  base::TrimWhitespaceASCII(tokens[0], base::TRIM_ALL, &transform_type);
  return (transform_type == lite_page_directive() ||
          transform_type == empty_image_directive());
}

bool ContentLoFiDecider::IsLitePagePreviewRequested(
    const net::HttpRequestHeaders& headers) const {
  std::string accept_transform_header_value;
  if (!headers.GetHeader(chrome_proxy_accept_transform_header(),
                         &accept_transform_header_value)) {
    return false;
  }
  std::vector<std::string> tokens =
      base::SplitString(base::ToLowerASCII(accept_transform_header_value), ";",
                        base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  if (tokens.empty())
    return false;
  std::string transform_type;
  base::TrimWhitespaceASCII(tokens[0], base::TRIM_ALL, &transform_type);
  return transform_type == lite_page_directive();
}

void ContentLoFiDecider::RemoveAcceptTransformHeader(
    net::HttpRequestHeaders* headers) const {
  headers->RemoveHeader(chrome_proxy_accept_transform_header());
}

void ContentLoFiDecider::MaybeSetIgnorePreviewsBlacklistDirective(
    net::HttpRequestHeaders* headers) const {
  if (!headers || !params::AreLitePagesEnabledViaFlags() ||
      !IsLitePagePreviewRequested(*headers)) {
    return;
  }
  std::string chrome_proxy_header_value;
  headers->GetHeader(chrome_proxy_header(), &chrome_proxy_header_value);
  headers->RemoveHeader(chrome_proxy_header());
  if (!chrome_proxy_header_value.empty())
    chrome_proxy_header_value += ", ";
  chrome_proxy_header_value +=
      chrome_proxy_lite_page_ignore_blacklist_directive();
  headers->SetHeader(chrome_proxy_header(), chrome_proxy_header_value);
}

bool ContentLoFiDecider::ShouldRecordLoFiUMA(
    const net::URLRequest& request) const {
  const content::ResourceRequestInfo* request_info =
      content::ResourceRequestInfo::ForRequest(&request);

  // User is not using Lo-Fi.
  if (!request_info ||
      !(request_info->GetPreviewsState() & content::SERVER_LOFI_ON)) {
    return false;
  }

  return params::IsIncludedInLoFiEnabledFieldTrial() ||
         params::IsIncludedInLoFiControlFieldTrial();
}

}  // namespace data_reduction_proxy