File: clipboard_item.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (139 lines) | stat: -rw-r--r-- 5,265 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
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/clipboard/clipboard_item.h"

#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/clipboard/clipboard.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "ui/base/clipboard/clipboard_constants.h"

namespace blink {

class UnionToBlobResolverFunction final
    : public ThenCallable<V8UnionBlobOrString,
                          UnionToBlobResolverFunction,
                          Blob> {
 public:
  explicit UnionToBlobResolverFunction(const String& mime_type)
      : mime_type_(mime_type) {}

  Blob* React(ScriptState* script_state, V8UnionBlobOrString* union_value) {
    if (union_value->IsBlob()) {
      return union_value->GetAsBlob();
    } else if (union_value->IsString()) {
      // ClipboardItem::getType() returns a Blob, so we need to convert the
      // string to a Blob here.
      return Blob::Create(union_value->GetAsString().Span8(), mime_type_);
    }
    return nullptr;
  }

 private:
  String mime_type_;
};

// static
ClipboardItem* ClipboardItem::Create(
    const HeapVector<
        std::pair<String, MemberScriptPromise<V8UnionBlobOrString>>>&
        representations,
    ExceptionState& exception_state) {
  // Check that incoming dictionary isn't empty. If it is, it's possible that
  // Javascript bindings implicitly converted an Object (like a
  // ScriptPromise<V8UnionBlobOrString>) into {}, an empty dictionary.
  if (!representations.size()) {
    exception_state.ThrowTypeError("Empty dictionary argument");
    return nullptr;
  }
  return MakeGarbageCollected<ClipboardItem>(representations);
}

ClipboardItem::ClipboardItem(
    const HeapVector<
        std::pair<String, MemberScriptPromise<V8UnionBlobOrString>>>&
        representations) {
  for (const auto& representation : representations) {
    String web_custom_format =
        Clipboard::ParseWebCustomFormat(representation.first);
    if (web_custom_format.empty()) {
      // Any arbitrary type can be added to ClipboardItem, but there may not be
      // any read/write support for that type.
      // TODO(caseq,japhet): we can't pass typed promises from bindings yet, but
      // when we can, the type cast below should go away.
      representations_.emplace_back(representation.first,
                                    representation.second);
    } else {
      // Types with "web " prefix are special, so we do some level of MIME type
      // parsing here to get a valid web custom format type.
      // We want to ensure that the string after removing the "web " prefix is
      // a valid MIME type.
      // e.g. "web text/html" is a web custom MIME type & "text/html" is a
      // well-known MIME type. Removing the "web " prefix makes it hard to
      // differentiate between the two.
      // TODO(caseq,japhet): we can't pass typed promises from bindings yet, but
      // when we can, the type cast below should go away.
      String web_custom_format_string =
          String::Format("%s%s", ui::kWebClipboardFormatPrefix,
                         web_custom_format.Utf8().c_str());
      representations_.emplace_back(web_custom_format_string,
                                    representation.second);
      custom_format_types_.push_back(web_custom_format_string);
    }
  }
}

Vector<String> ClipboardItem::types() const {
  Vector<String> types;
  types.ReserveInitialCapacity(representations_.size());
  for (const auto& item : representations_) {
    types.push_back(item.first);
  }
  return types;
}

ScriptPromise<Blob> ClipboardItem::getType(
    ScriptState* script_state,
    const String& type,
    ExceptionState& exception_state) const {
  for (const auto& item : representations_) {
    if (type == item.first) {
      return item.second.Unwrap().Then(
          script_state,
          MakeGarbageCollected<UnionToBlobResolverFunction>(type));
    }
  }

  exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
                                    "The type was not found");
  return ScriptPromise<Blob>();
}

// static
bool ClipboardItem::supports(const String& type) {
  if (type.length() >= mojom::blink::ClipboardHost::kMaxFormatSize) {
    return false;
  }

  if (!Clipboard::ParseWebCustomFormat(type).empty()) {
    return true;
  }

  // TODO(https://crbug.com/1029857): Add support for other types.
  return type == ui::kMimeTypePng || type == ui::kMimeTypePlainText ||
         type == ui::kMimeTypeHtml || type == ui::kMimeTypeSvg;
}

void ClipboardItem::Trace(Visitor* visitor) const {
  visitor->Trace(representations_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink