File: data_deleter.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 (163 lines) | stat: -rw-r--r-- 5,964 bytes parent folder | download | duplicates (5)
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
// 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/data_deleter.h"

#include "base/barrier_closure.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/task_runner.h"
#include "chrome/browser/extensions/chrome_extension_cookies.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.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/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "extensions/browser/api/storage/storage_frontend.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"

using base::WeakPtr;
using content::BrowserContext;
using content::BrowserThread;
using content::StoragePartition;

namespace extensions {

namespace {

// Helper function that deletes data of a given |storage_origin| in a given
// |partition| and synchronously invokes |done_callback| once the data is
// deleted.
void DeleteOrigin(Profile* profile,
                  StoragePartition* partition,
                  const GURL& origin,
                  base::OnceClosure done_callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(profile);
  DCHECK(partition);

  if (origin.SchemeIs(kExtensionScheme)) {
    auto subtask_done_callback =
        base::BarrierClosure(2, std::move(done_callback));

    // TODO(ajwong): Cookies are not properly isolated for
    // chrome-extension:// scheme.  (http://crbug.com/158386).
    //
    // However, no isolated apps actually can write to kExtensionScheme
    // origins. Thus, it is benign to delete from the
    // RequestContextForExtensions because there's nothing stored there. We
    // preserve this code path without checking for isolation because it's
    // simpler than special casing.  This code should go away once we merge
    // the various URLRequestContexts (http://crbug.com/159193).
    partition->ClearDataForOrigin(
        ~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
        StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, origin,
        subtask_done_callback);

    // Delete cookies separately from other data so that the request context
    // for extensions doesn't need to be passed into the StoragePartition.
    ChromeExtensionCookies::Get(profile)->ClearCookies(origin,
                                                       subtask_done_callback);
  } else {
    // We don't need to worry about the media request context because that
    // shares the same cookie store as the main request context.
    partition->ClearDataForOrigin(
        ~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
        StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, origin,
        std::move(done_callback));
  }
}

void OnNeedsToGarbageCollectIsolatedStorage(WeakPtr<Profile> profile) {
  if (profile) {
    profile->GetPrefs()->SetBoolean(
        prefs::kShouldGarbageCollectStoragePartitions, true);
  }
}

}  // namespace

// static
void DataDeleter::StartDeleting(Profile* profile,
                                const Extension* extension,
                                base::OnceClosure done_callback) {
  DCHECK(profile);
  DCHECK(!profile->IsOffTheRecord());
  DCHECK(extension);

  // Storage deletion can take a couple different tasks, depending on the
  // extension. The number of tasks is precomputed and passed to a barrier
  // closure.
  bool has_isolated_storage = false;
  bool delete_extension_origin = false;
  bool delete_web_url_origin = false;
  bool delete_extension_storage = false;
  int num_tasks = 0;

  GURL launch_web_url_origin;
  StoragePartition* partition = nullptr;

  if (util::HasIsolatedStorage(*extension, profile)) {
    has_isolated_storage = true;
    ++num_tasks;
  } else {
    delete_extension_origin = true;
    ++num_tasks;

    launch_web_url_origin =
        AppLaunchInfo::GetLaunchWebURL(extension).DeprecatedGetOriginAsURL();
    partition =
        util::GetStoragePartitionForExtensionId(extension->id(), profile);

    ExtensionSpecialStoragePolicy* storage_policy =
        profile->GetExtensionSpecialStoragePolicy();
    if (storage_policy->NeedsProtection(extension) &&
        !storage_policy->IsStorageProtected(launch_web_url_origin)) {
      delete_web_url_origin = true;
      ++num_tasks;
    }
  }

  // StorageFrontend may not exist in unit tests.
  StorageFrontend* frontend = StorageFrontend::Get(profile);
  if (frontend) {
    delete_extension_storage = true;
    ++num_tasks;
  }

  auto subtask_done_callback =
      base::BarrierClosure(num_tasks, std::move(done_callback));
  if (has_isolated_storage) {
    profile->AsyncObliterateStoragePartition(
        util::GetPartitionDomainForExtension(extension),
        base::BindOnce(&OnNeedsToGarbageCollectIsolatedStorage,
                       profile->GetWeakPtr()),
        subtask_done_callback);
  }
  if (delete_extension_origin) {
    DCHECK(partition);
    DeleteOrigin(profile, partition, extension->url(), subtask_done_callback);
  }
  if (delete_web_url_origin) {
    DCHECK(partition);
    DCHECK(!launch_web_url_origin.is_empty());
    DeleteOrigin(profile, partition, launch_web_url_origin,
                 subtask_done_callback);
  }
  if (delete_extension_storage) {
    frontend->DeleteStorageSoon(extension->id(), subtask_done_callback);
  }
}

}  // namespace extensions