File: navigation_extension_enabler.cc

package info (click to toggle)
chromium 141.0.7390.107-1~deb13u1
  • links: PTS, VCS
  • area: main
  • in suites: trixie-proposed-updates
  • size: 6,246,428 kB
  • sloc: cpp: 35,264,965; ansic: 7,169,920; javascript: 4,250,185; python: 1,460,635; asm: 950,788; xml: 751,751; pascal: 187,972; sh: 89,459; perl: 88,691; objc: 79,953; sql: 53,924; cs: 44,622; fortran: 24,137; makefile: 22,313; tcl: 15,277; php: 14,018; yacc: 8,995; ruby: 7,553; awk: 3,720; lisp: 3,096; lex: 1,330; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 4,944 bytes parent folder | download | duplicates (4)
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
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/navigation_extension_enabler.h"

#include <memory>

#include "base/functional/bind.h"
#include "chrome/browser/extensions/extension_service.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"

namespace extensions {

NavigationExtensionEnabler::NavigationExtensionEnabler(
    content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents),
      content::WebContentsUserData<NavigationExtensionEnabler>(*web_contents) {
  extension_registry_observation_.Observe(
      ExtensionRegistry::Get(web_contents->GetBrowserContext()));
}

NavigationExtensionEnabler::~NavigationExtensionEnabler() = default;

void NavigationExtensionEnabler::NavigationEntryCommitted(
    const content::LoadCommittedDetails& load_details) {
  PromptToEnableExtensionIfNecessary(load_details.entry->GetURL());
}

void NavigationExtensionEnabler::PromptToEnableExtensionIfNecessary(
    const GURL& url) {
  // Bail out if we're already running a prompt.
  if (!in_progress_prompt_extension_id_.empty()) {
    return;
  }

  // NOTE: We only consider chrome-extension:// urls, and deliberately don't
  // consider hosted app urls. This is because it's really annoying to visit the
  // site associated with a hosted app (like calendar.google.com or
  // drive.google.com) and have it repeatedly prompt you to re-enable an item.
  // Visiting a chrome-extension:// url is a much stronger signal, and, without
  // the item enabled, we won't show anything.
  // TODO(devlin): While true, I still wonder how useful this is. We should get
  // metrics.
  if (!url.SchemeIs(kExtensionScheme)) {
    return;
  }

  const Extension* extension =
      ExtensionRegistry::Get(web_contents()->GetBrowserContext())
          ->disabled_extensions()
          .GetExtensionOrAppByURL(url);
  if (!extension) {
    return;
  }

  ExtensionPrefs* extension_prefs =
      ExtensionPrefs::Get(web_contents()->GetBrowserContext());
  // TODO(devlin): Why do we only consider extensions that escalate permissions?
  // Maybe because it's the only one we have a good prompt for?
  if (!extension_prefs->DidExtensionEscalatePermissions(extension->id())) {
    return;
  }

  // Keep track of the extension id we're prompting for. These must be reset in
  // OnInstallPromptDone.
  in_progress_prompt_extension_id_ = extension->id();

  extension_install_prompt_ =
      std::make_unique<ExtensionInstallPrompt>(web_contents());
  ExtensionInstallPrompt::PromptType type =
      ExtensionInstallPrompt::GetReEnablePromptTypeForExtension(
          web_contents()->GetBrowserContext(), extension);
  extension_install_prompt_->ShowDialog(
      base::BindRepeating(&NavigationExtensionEnabler::OnInstallPromptDone,
                          weak_factory_.GetWeakPtr()),
      extension, nullptr,
      std::make_unique<ExtensionInstallPrompt::Prompt>(type),
      ExtensionInstallPrompt::GetDefaultShowDialogCallback());
}

void NavigationExtensionEnabler::OnInstallPromptDone(
    ExtensionInstallPrompt::DoneCallbackPayload payload) {
  // This dialog doesn't support the "withhold permissions" checkbox.
  DCHECK_NE(payload.result,
            ExtensionInstallPrompt::Result::ACCEPTED_WITH_WITHHELD_PERMISSIONS);

  // The extension was already uninstalled.
  if (in_progress_prompt_extension_id_.empty()) {
    return;
  }

  ExtensionRegistry* extension_registry =
      ExtensionRegistry::Get(web_contents()->GetBrowserContext());
  const Extension* extension = extension_registry->GetExtensionById(
      in_progress_prompt_extension_id_, ExtensionRegistry::EVERYTHING);
  CHECK(extension);

  if (payload.result == ExtensionInstallPrompt::Result::ACCEPTED) {
    ExtensionRegistrar* extension_registrar =
        ExtensionRegistrar::Get(web_contents()->GetBrowserContext());
    // Grant permissions, re-enable the extension, and then reload the tab.
    extension_registrar->GrantPermissionsAndEnableExtension(*extension);
    web_contents()->GetController().Reload(content::ReloadType::NORMAL, true);
  }

  in_progress_prompt_extension_id_.clear();
  extension_install_prompt_.reset();
}

void NavigationExtensionEnabler::OnExtensionUninstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UninstallReason reason) {
  if (in_progress_prompt_extension_id_.empty() ||
      in_progress_prompt_extension_id_ != extension->id()) {
    return;
  }

  in_progress_prompt_extension_id_ = std::string();
  extension_install_prompt_.reset();
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(NavigationExtensionEnabler);

}  // namespace extensions