File: mojo_safe_browsing_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (172 lines) | stat: -rw-r--r-- 6,807 bytes parent folder | download | duplicates (6)
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
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/safe_browsing/content/browser/mojo_safe_browsing_impl.h"

#include <memory>

#include "base/functional/bind.h"
#include "base/supports_user_data.h"
#include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h"
#include "components/safe_browsing/core/common/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/load_flags.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"

namespace safe_browsing {
namespace {

content::WebContents* GetWebContentsFromToken(
    int render_process_id,
    const std::optional<blink::LocalFrameToken>& frame_token) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!frame_token) {
    return nullptr;
  }
  content::RenderFrameHost* render_frame_host =
      content::RenderFrameHost::FromFrameToken(
          content::GlobalRenderFrameHostToken(render_process_id,
                                              frame_token.value()));
  if (!render_frame_host) {
    return nullptr;
  }

  return content::WebContents::FromRenderFrameHost(render_frame_host);
}

}  // namespace

MojoSafeBrowsingImpl::MojoSafeBrowsingImpl(
    scoped_refptr<UrlCheckerDelegate> delegate,
    int render_process_id,
    base::SupportsUserData* user_data)
    : delegate_(std::move(delegate)),
      render_process_id_(render_process_id),
      user_data_(user_data) {
  // It is safe to bind |this| as Unretained because |receivers_| is owned by
  // |this| and will not call this callback after it is destroyed.
  receivers_.set_disconnect_handler(base::BindRepeating(
      &MojoSafeBrowsingImpl::OnMojoDisconnect, base::Unretained(this)));
}

MojoSafeBrowsingImpl::~MojoSafeBrowsingImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}

// static
void MojoSafeBrowsingImpl::MaybeCreate(
    int render_process_id,
    const base::RepeatingCallback<scoped_refptr<UrlCheckerDelegate>()>&
        delegate_getter,
    mojo::PendingReceiver<mojom::SafeBrowsing> receiver) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  scoped_refptr<UrlCheckerDelegate> delegate = delegate_getter.Run();

  if (!delegate) {
    return;
  }

  base::SupportsUserData* user_data;
  content::RenderProcessHost* rph =
      content::RenderProcessHost::FromID(render_process_id);
  DCHECK(rph);
  user_data = rph->GetBrowserContext();

  std::unique_ptr<MojoSafeBrowsingImpl> impl(new MojoSafeBrowsingImpl(
      std::move(delegate), render_process_id, user_data));
  impl->Clone(std::move(receiver));

  // Need to store the value of |impl.get()| in a temp variable instead of
  // getting the value on the same line as |std::move(impl)|, because the
  // evaluation order is unspecified.
  const void* key = impl.get();
  user_data->SetUserData(key, std::move(impl));
}

void MojoSafeBrowsingImpl::CreateCheckerAndCheck(
    const std::optional<blink::LocalFrameToken>& frame_token,
    mojo::PendingReceiver<mojom::SafeBrowsingUrlChecker> receiver,
    const GURL& url,
    const std::string& method,
    const net::HttpRequestHeaders& headers,
    int32_t load_flags,
    bool has_user_gesture,
    bool originated_from_service_worker,
    CreateCheckerAndCheckCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  std::optional<base::UnguessableToken> sb_frame_token;
  if (frame_token) {
    sb_frame_token = frame_token->value();
  }
  if (delegate_->ShouldSkipRequestCheck(url, content::FrameTreeNodeId().value(),
                                        render_process_id_, sb_frame_token,
                                        originated_from_service_worker)) {
    // Ensure that we don't destroy an uncalled CreateCheckerAndCheckCallback
    if (callback) {
      std::move(callback).Run(true /* proceed */,
                              false /* showed_interstitial */);
    }

    // This will drop |receiver|. The result is that the renderer side will
    // consider all URLs in the redirect chain of this receiver as safe.
    return;
  }

  // This is not called for frame resources, and real time URL checks currently
  // only support main frame resources. If we extend real time URL checks to
  // support non-main frames, we will need to provide the user preferences,
  // url_lookup_service regarding real time lookup here. If we extend
  // hash-prefix real-time checks to support non-main frames, we will need to
  // provide the hash_realtime_service_on_ui here.
  auto checker_impl = std::make_unique<SafeBrowsingUrlCheckerImpl>(
      headers, static_cast<int>(load_flags), has_user_gesture, delegate_,
      base::BindRepeating(&GetWebContentsFromToken, render_process_id_,
                          frame_token),
      /*weak_web_state=*/nullptr, render_process_id_, sb_frame_token,
      content::FrameTreeNodeId().value(),
      /*navigation_id=*/std::nullopt,
      /*url_real_time_lookup_enabled=*/false,
      /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true,
      /*url_lookup_service_metric_suffix=*/".None",
      content::GetUIThreadTaskRunner({}),
      /*url_lookup_service=*/nullptr,
      /*hash_realtime_service_on_ui=*/nullptr,
      /*hash_realtime_selection=*/
      hash_realtime_utils::HashRealTimeSelection::kNone,
      /*is_async_check=*/false, /*check_allowlist_before_hash_database=*/false,
      SessionID::InvalidValue(), /*referring_app_info=*/std::nullopt);
  auto weak_impl = checker_impl->WeakPtr();

  checker_impl->CheckUrl(url, method,
                         mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                             std::move(callback),
                             /*proceed=*/true, /*showed_interstitial=*/false));
  CHECK(weak_impl);  // This is to ensure calling CheckUrl doesn't delete itself
  mojo::MakeSelfOwnedReceiver(std::move(checker_impl), std::move(receiver));
}

void MojoSafeBrowsingImpl::Clone(
    mojo::PendingReceiver<mojom::SafeBrowsing> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void MojoSafeBrowsingImpl::OnMojoDisconnect() {
  if (receivers_.empty()) {
    user_data_->RemoveUserData(this);
    // This object is destroyed.
  }
}

}  // namespace safe_browsing