chore: modernize Value usage in converters (#34794)
* chore: modernize Value usage in converters * Date is parsed as an empty object now
This commit is contained in:
		
					parent
					
						
							
								d28ed0da20
							
						
					
				
			
			
				commit
				
					
						0ee7f14190
					
				
			
		
					 34 changed files with 203 additions and 829 deletions
				
			
		| 
						 | 
				
			
			@ -643,8 +643,6 @@ filenames = {
 | 
			
		|||
    "shell/common/process_util.h",
 | 
			
		||||
    "shell/common/skia_util.cc",
 | 
			
		||||
    "shell/common/skia_util.h",
 | 
			
		||||
    "shell/common/v8_value_converter.cc",
 | 
			
		||||
    "shell/common/v8_value_converter.h",
 | 
			
		||||
    "shell/common/v8_value_serializer.cc",
 | 
			
		||||
    "shell/common/v8_value_serializer.h",
 | 
			
		||||
    "shell/common/world_ids.h",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -288,7 +288,7 @@ void BaseWindow::OnExecuteAppCommand(const std::string& command_name) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void BaseWindow::OnTouchBarItemResult(const std::string& item_id,
 | 
			
		||||
                                      const base::DictionaryValue& details) {
 | 
			
		||||
                                      const base::Value::Dict& details) {
 | 
			
		||||
  Emit("-touch-bar-interaction", item_id, details);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
 | 
			
		|||
  void OnWindowAlwaysOnTopChanged() override;
 | 
			
		||||
  void OnExecuteAppCommand(const std::string& command_name) override;
 | 
			
		||||
  void OnTouchBarItemResult(const std::string& item_id,
 | 
			
		||||
                            const base::DictionaryValue& details) override;
 | 
			
		||||
                            const base::Value::Dict& details) override;
 | 
			
		||||
  void OnNewWindowForTab() override;
 | 
			
		||||
  void OnSystemContextMenu(int x, int y, bool* prevent_default) override;
 | 
			
		||||
#if BUILDFLAG(IS_WIN)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,9 +42,10 @@ struct Converter<base::trace_event::TraceConfig> {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    base::DictionaryValue memory_dump_config;
 | 
			
		||||
    base::Value::Dict memory_dump_config;
 | 
			
		||||
    if (ConvertFromV8(isolate, val, &memory_dump_config)) {
 | 
			
		||||
      *out = base::trace_event::TraceConfig(memory_dump_config);
 | 
			
		||||
      *out = base::trace_event::TraceConfig(
 | 
			
		||||
          base::Value(std::move(memory_dump_config)));
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,27 +117,27 @@ bool MatchesDomain(std::string filter, const std::string& domain) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Returns whether |cookie| matches |filter|.
 | 
			
		||||
bool MatchesCookie(const base::Value& filter,
 | 
			
		||||
bool MatchesCookie(const base::Value::Dict& filter,
 | 
			
		||||
                   const net::CanonicalCookie& cookie) {
 | 
			
		||||
  const std::string* str;
 | 
			
		||||
  if ((str = filter.FindStringKey("name")) && *str != cookie.Name())
 | 
			
		||||
  if ((str = filter.FindString("name")) && *str != cookie.Name())
 | 
			
		||||
    return false;
 | 
			
		||||
  if ((str = filter.FindStringKey("path")) && *str != cookie.Path())
 | 
			
		||||
  if ((str = filter.FindString("path")) && *str != cookie.Path())
 | 
			
		||||
    return false;
 | 
			
		||||
  if ((str = filter.FindStringKey("domain")) &&
 | 
			
		||||
  if ((str = filter.FindString("domain")) &&
 | 
			
		||||
      !MatchesDomain(*str, cookie.Domain()))
 | 
			
		||||
    return false;
 | 
			
		||||
  absl::optional<bool> secure_filter = filter.FindBoolKey("secure");
 | 
			
		||||
  absl::optional<bool> secure_filter = filter.FindBool("secure");
 | 
			
		||||
  if (secure_filter && *secure_filter == cookie.IsSecure())
 | 
			
		||||
    return false;
 | 
			
		||||
  absl::optional<bool> session_filter = filter.FindBoolKey("session");
 | 
			
		||||
  absl::optional<bool> session_filter = filter.FindBool("session");
 | 
			
		||||
  if (session_filter && *session_filter != !cookie.IsPersistent())
 | 
			
		||||
    return false;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
 | 
			
		||||
void FilterCookies(const base::Value& filter,
 | 
			
		||||
void FilterCookies(base::Value::Dict filter,
 | 
			
		||||
                   gin_helper::Promise<net::CookieList> promise,
 | 
			
		||||
                   const net::CookieList& cookies) {
 | 
			
		||||
  net::CookieList result;
 | 
			
		||||
| 
						 | 
				
			
			@ -149,11 +149,11 @@ void FilterCookies(const base::Value& filter,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void FilterCookieWithStatuses(
 | 
			
		||||
    const base::Value& filter,
 | 
			
		||||
    base::Value::Dict filter,
 | 
			
		||||
    gin_helper::Promise<net::CookieList> promise,
 | 
			
		||||
    const net::CookieAccessResultList& list,
 | 
			
		||||
    const net::CookieAccessResultList& excluded_list) {
 | 
			
		||||
  FilterCookies(filter, std::move(promise),
 | 
			
		||||
  FilterCookies(std::move(filter), std::move(promise),
 | 
			
		||||
                net::cookie_util::StripAccessResults(list));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ v8::Local<v8::Promise> Cookies::Get(v8::Isolate* isolate,
 | 
			
		|||
  auto* storage_partition = browser_context_->GetDefaultStoragePartition();
 | 
			
		||||
  auto* manager = storage_partition->GetCookieManagerForBrowserProcess();
 | 
			
		||||
 | 
			
		||||
  base::DictionaryValue dict;
 | 
			
		||||
  base::Value::Dict dict;
 | 
			
		||||
  gin::ConvertFromV8(isolate, filter.GetHandle(), &dict);
 | 
			
		||||
 | 
			
		||||
  std::string url;
 | 
			
		||||
| 
						 | 
				
			
			@ -280,31 +280,31 @@ v8::Local<v8::Promise> Cookies::Remove(v8::Isolate* isolate,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Promise> Cookies::Set(v8::Isolate* isolate,
 | 
			
		||||
                                    const base::DictionaryValue& details) {
 | 
			
		||||
                                    base::Value::Dict details) {
 | 
			
		||||
  gin_helper::Promise<void> promise(isolate);
 | 
			
		||||
  v8::Local<v8::Promise> handle = promise.GetHandle();
 | 
			
		||||
 | 
			
		||||
  const std::string* url_string = details.FindStringKey("url");
 | 
			
		||||
  const std::string* url_string = details.FindString("url");
 | 
			
		||||
  if (!url_string) {
 | 
			
		||||
    promise.RejectWithErrorMessage("Missing required option 'url'");
 | 
			
		||||
    return handle;
 | 
			
		||||
  }
 | 
			
		||||
  const std::string* name = details.FindStringKey("name");
 | 
			
		||||
  const std::string* value = details.FindStringKey("value");
 | 
			
		||||
  const std::string* domain = details.FindStringKey("domain");
 | 
			
		||||
  const std::string* path = details.FindStringKey("path");
 | 
			
		||||
  bool http_only = details.FindBoolKey("httpOnly").value_or(false);
 | 
			
		||||
  const std::string* same_site_string = details.FindStringKey("sameSite");
 | 
			
		||||
  const std::string* name = details.FindString("name");
 | 
			
		||||
  const std::string* value = details.FindString("value");
 | 
			
		||||
  const std::string* domain = details.FindString("domain");
 | 
			
		||||
  const std::string* path = details.FindString("path");
 | 
			
		||||
  bool http_only = details.FindBool("httpOnly").value_or(false);
 | 
			
		||||
  const std::string* same_site_string = details.FindString("sameSite");
 | 
			
		||||
  net::CookieSameSite same_site;
 | 
			
		||||
  std::string error = StringToCookieSameSite(same_site_string, &same_site);
 | 
			
		||||
  if (!error.empty()) {
 | 
			
		||||
    promise.RejectWithErrorMessage(error);
 | 
			
		||||
    return handle;
 | 
			
		||||
  }
 | 
			
		||||
  bool secure = details.FindBoolKey("secure").value_or(
 | 
			
		||||
  bool secure = details.FindBool("secure").value_or(
 | 
			
		||||
      same_site == net::CookieSameSite::NO_RESTRICTION);
 | 
			
		||||
  bool same_party =
 | 
			
		||||
      details.FindBoolKey("sameParty")
 | 
			
		||||
      details.FindBool("sameParty")
 | 
			
		||||
          .value_or(secure && same_site != net::CookieSameSite::STRICT_MODE);
 | 
			
		||||
 | 
			
		||||
  GURL url(url_string ? *url_string : "");
 | 
			
		||||
| 
						 | 
				
			
			@ -317,10 +317,9 @@ v8::Local<v8::Promise> Cookies::Set(v8::Isolate* isolate,
 | 
			
		|||
 | 
			
		||||
  auto canonical_cookie = net::CanonicalCookie::CreateSanitizedCookie(
 | 
			
		||||
      url, name ? *name : "", value ? *value : "", domain ? *domain : "",
 | 
			
		||||
      path ? *path : "",
 | 
			
		||||
      ParseTimeProperty(details.FindDoubleKey("creationDate")),
 | 
			
		||||
      ParseTimeProperty(details.FindDoubleKey("expirationDate")),
 | 
			
		||||
      ParseTimeProperty(details.FindDoubleKey("lastAccessDate")), secure,
 | 
			
		||||
      path ? *path : "", ParseTimeProperty(details.FindDouble("creationDate")),
 | 
			
		||||
      ParseTimeProperty(details.FindDouble("expirationDate")),
 | 
			
		||||
      ParseTimeProperty(details.FindDouble("lastAccessDate")), secure,
 | 
			
		||||
      http_only, same_site, net::COOKIE_PRIORITY_DEFAULT, same_party,
 | 
			
		||||
      absl::nullopt);
 | 
			
		||||
  if (!canonical_cookie || !canonical_cookie->IsCanonical()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "base/callback_list.h"
 | 
			
		||||
#include "base/values.h"
 | 
			
		||||
#include "gin/handle.h"
 | 
			
		||||
#include "net/cookies/canonical_cookie.h"
 | 
			
		||||
#include "net/cookies/cookie_change_dispatcher.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -15,10 +16,6 @@
 | 
			
		|||
#include "shell/common/gin_helper/promise.h"
 | 
			
		||||
#include "shell/common/gin_helper/trackable_object.h"
 | 
			
		||||
 | 
			
		||||
namespace base {
 | 
			
		||||
class DictionaryValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace gin_helper {
 | 
			
		||||
class Dictionary;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +48,7 @@ class Cookies : public gin::Wrappable<Cookies>,
 | 
			
		|||
 | 
			
		||||
  v8::Local<v8::Promise> Get(v8::Isolate*,
 | 
			
		||||
                             const gin_helper::Dictionary& filter);
 | 
			
		||||
  v8::Local<v8::Promise> Set(v8::Isolate*,
 | 
			
		||||
                             const base::DictionaryValue& details);
 | 
			
		||||
  v8::Local<v8::Promise> Set(v8::Isolate*, base::Value::Dict details);
 | 
			
		||||
  v8::Local<v8::Promise> Remove(v8::Isolate*,
 | 
			
		||||
                                const GURL& url,
 | 
			
		||||
                                const std::string& name);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,44 +45,35 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
 | 
			
		|||
 | 
			
		||||
  base::StringPiece message_str(reinterpret_cast<const char*>(message.data()),
 | 
			
		||||
                                message.size());
 | 
			
		||||
  std::unique_ptr<base::Value> parsed_message =
 | 
			
		||||
      base::JSONReader::ReadDeprecated(message_str,
 | 
			
		||||
                                       base::JSON_REPLACE_INVALID_CHARACTERS);
 | 
			
		||||
  absl::optional<base::Value> parsed_message = base::JSONReader::Read(
 | 
			
		||||
      message_str, base::JSON_REPLACE_INVALID_CHARACTERS);
 | 
			
		||||
  if (!parsed_message || !parsed_message->is_dict())
 | 
			
		||||
    return;
 | 
			
		||||
  auto* dict = static_cast<base::DictionaryValue*>(parsed_message.get());
 | 
			
		||||
  int id;
 | 
			
		||||
  if (!dict->GetInteger("id", &id)) {
 | 
			
		||||
    std::string method;
 | 
			
		||||
    if (!dict->GetString("method", &method))
 | 
			
		||||
  base::Value::Dict& dict = parsed_message->GetDict();
 | 
			
		||||
  absl::optional<int> id = dict.FindInt("id");
 | 
			
		||||
  if (!id) {
 | 
			
		||||
    std::string* method = dict.FindString("method");
 | 
			
		||||
    if (!method)
 | 
			
		||||
      return;
 | 
			
		||||
    std::string session_id;
 | 
			
		||||
    dict->GetString("sessionId", &session_id);
 | 
			
		||||
    base::DictionaryValue* params_value = nullptr;
 | 
			
		||||
    base::DictionaryValue params;
 | 
			
		||||
    if (dict->GetDictionary("params", ¶ms_value))
 | 
			
		||||
      params.Swap(params_value);
 | 
			
		||||
    Emit("message", method, params, session_id);
 | 
			
		||||
    std::string* session_id = dict.FindString("sessionId");
 | 
			
		||||
    base::Value::Dict* params = dict.FindDict("params");
 | 
			
		||||
    Emit("message", *method, params ? std::move(*params) : base::Value::Dict(),
 | 
			
		||||
         session_id ? *session_id : "");
 | 
			
		||||
  } else {
 | 
			
		||||
    auto it = pending_requests_.find(id);
 | 
			
		||||
    auto it = pending_requests_.find(*id);
 | 
			
		||||
    if (it == pending_requests_.end())
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    gin_helper::Promise<base::DictionaryValue> promise = std::move(it->second);
 | 
			
		||||
    gin_helper::Promise<base::Value::Dict> promise = std::move(it->second);
 | 
			
		||||
    pending_requests_.erase(it);
 | 
			
		||||
 | 
			
		||||
    base::DictionaryValue* error = nullptr;
 | 
			
		||||
    if (dict->GetDictionary("error", &error)) {
 | 
			
		||||
      std::string message;
 | 
			
		||||
      error->GetString("message", &message);
 | 
			
		||||
      promise.RejectWithErrorMessage(message);
 | 
			
		||||
    base::Value::Dict* error = dict.FindDict("error");
 | 
			
		||||
    if (error) {
 | 
			
		||||
      std::string* message = error->FindString("message");
 | 
			
		||||
      promise.RejectWithErrorMessage(message ? *message : "");
 | 
			
		||||
    } else {
 | 
			
		||||
      base::DictionaryValue* result_body = nullptr;
 | 
			
		||||
      base::DictionaryValue result;
 | 
			
		||||
      if (dict->GetDictionary("result", &result_body)) {
 | 
			
		||||
        result.Swap(result_body);
 | 
			
		||||
      }
 | 
			
		||||
      promise.Resolve(result);
 | 
			
		||||
      base::Value::Dict* result = dict.FindDict("result");
 | 
			
		||||
      promise.Resolve(result ? std::move(*result) : base::Value::Dict());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +124,7 @@ void Debugger::Detach() {
 | 
			
		|||
 | 
			
		||||
v8::Local<v8::Promise> Debugger::SendCommand(gin::Arguments* args) {
 | 
			
		||||
  v8::Isolate* isolate = args->isolate();
 | 
			
		||||
  gin_helper::Promise<base::DictionaryValue> promise(isolate);
 | 
			
		||||
  gin_helper::Promise<base::Value::Dict> promise(isolate);
 | 
			
		||||
  v8::Local<v8::Promise> handle = promise.GetHandle();
 | 
			
		||||
 | 
			
		||||
  if (!agent_host_) {
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +138,7 @@ v8::Local<v8::Promise> Debugger::SendCommand(gin::Arguments* args) {
 | 
			
		|||
    return handle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  base::DictionaryValue command_params;
 | 
			
		||||
  base::Value::Dict command_params;
 | 
			
		||||
  args->GetNext(&command_params);
 | 
			
		||||
 | 
			
		||||
  std::string session_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -156,22 +147,21 @@ v8::Local<v8::Promise> Debugger::SendCommand(gin::Arguments* args) {
 | 
			
		|||
    return handle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  base::DictionaryValue request;
 | 
			
		||||
  base::Value::Dict request;
 | 
			
		||||
  int request_id = ++previous_request_id_;
 | 
			
		||||
  pending_requests_.emplace(request_id, std::move(promise));
 | 
			
		||||
  request.SetInteger("id", request_id);
 | 
			
		||||
  request.SetString("method", method);
 | 
			
		||||
  if (!command_params.DictEmpty()) {
 | 
			
		||||
    request.Set("params",
 | 
			
		||||
                base::Value::ToUniquePtrValue(command_params.Clone()));
 | 
			
		||||
  request.Set("id", request_id);
 | 
			
		||||
  request.Set("method", method);
 | 
			
		||||
  if (!command_params.empty()) {
 | 
			
		||||
    request.Set("params", base::Value(std::move(command_params)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!session_id.empty()) {
 | 
			
		||||
    request.SetString("sessionId", session_id);
 | 
			
		||||
    request.Set("sessionId", session_id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::string json_args;
 | 
			
		||||
  base::JSONWriter::Write(request, &json_args);
 | 
			
		||||
  base::JSONWriter::Write(base::Value(std::move(request)), &json_args);
 | 
			
		||||
  agent_host_->DispatchProtocolMessage(
 | 
			
		||||
      this, base::as_bytes(base::make_span(json_args)));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ class Debugger : public gin::Wrappable<Debugger>,
 | 
			
		|||
 | 
			
		||||
 private:
 | 
			
		||||
  using PendingRequestMap =
 | 
			
		||||
      std::map<int, gin_helper::Promise<base::DictionaryValue>>;
 | 
			
		||||
      std::map<int, gin_helper::Promise<base::Value::Dict>>;
 | 
			
		||||
 | 
			
		||||
  void Attach(gin::Arguments* args);
 | 
			
		||||
  bool IsAttached();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1160,7 +1160,7 @@ gin::Handle<Session> Session::CreateFrom(
 | 
			
		|||
// static
 | 
			
		||||
gin::Handle<Session> Session::FromPartition(v8::Isolate* isolate,
 | 
			
		||||
                                            const std::string& partition,
 | 
			
		||||
                                            base::DictionaryValue options) {
 | 
			
		||||
                                            base::Value::Dict options) {
 | 
			
		||||
  ElectronBrowserContext* browser_context;
 | 
			
		||||
  if (partition.empty()) {
 | 
			
		||||
    browser_context =
 | 
			
		||||
| 
						 | 
				
			
			@ -1265,7 +1265,7 @@ v8::Local<v8::Value> FromPartition(const std::string& partition,
 | 
			
		|||
    args->ThrowTypeError("Session can only be received when app is ready");
 | 
			
		||||
    return v8::Null(args->isolate());
 | 
			
		||||
  }
 | 
			
		||||
  base::DictionaryValue options;
 | 
			
		||||
  base::Value::Dict options;
 | 
			
		||||
  args->GetNext(&options);
 | 
			
		||||
  return Session::FromPartition(args->isolate(), partition, std::move(options))
 | 
			
		||||
      .ToV8();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,10 +75,9 @@ class Session : public gin::Wrappable<Session>,
 | 
			
		|||
  static Session* FromBrowserContext(content::BrowserContext* context);
 | 
			
		||||
 | 
			
		||||
  // Gets the Session of |partition|.
 | 
			
		||||
  static gin::Handle<Session> FromPartition(
 | 
			
		||||
      v8::Isolate* isolate,
 | 
			
		||||
  static gin::Handle<Session> FromPartition(v8::Isolate* isolate,
 | 
			
		||||
                                            const std::string& partition,
 | 
			
		||||
      base::DictionaryValue options = base::DictionaryValue());
 | 
			
		||||
                                            base::Value::Dict options = {});
 | 
			
		||||
 | 
			
		||||
  ElectronBrowserContext* browser_context() const { return browser_context_; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,18 +72,18 @@ class SystemPreferences
 | 
			
		|||
      void(const std::string&, base::Value, const std::string&)>;
 | 
			
		||||
 | 
			
		||||
  void PostNotification(const std::string& name,
 | 
			
		||||
                        base::DictionaryValue user_info,
 | 
			
		||||
                        base::Value::Dict user_info,
 | 
			
		||||
                        gin::Arguments* args);
 | 
			
		||||
  int SubscribeNotification(v8::Local<v8::Value> maybe_name,
 | 
			
		||||
                            const NotificationCallback& callback);
 | 
			
		||||
  void UnsubscribeNotification(int id);
 | 
			
		||||
  void PostLocalNotification(const std::string& name,
 | 
			
		||||
                             base::DictionaryValue user_info);
 | 
			
		||||
                             base::Value::Dict user_info);
 | 
			
		||||
  int SubscribeLocalNotification(v8::Local<v8::Value> maybe_name,
 | 
			
		||||
                                 const NotificationCallback& callback);
 | 
			
		||||
  void UnsubscribeLocalNotification(int request_id);
 | 
			
		||||
  void PostWorkspaceNotification(const std::string& name,
 | 
			
		||||
                                 base::DictionaryValue user_info);
 | 
			
		||||
                                 base::Value::Dict user_info);
 | 
			
		||||
  int SubscribeWorkspaceNotification(v8::Local<v8::Value> maybe_name,
 | 
			
		||||
                                     const NotificationCallback& callback);
 | 
			
		||||
  void UnsubscribeWorkspaceNotification(int request_id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,7 +138,7 @@ NSNotificationCenter* GetNotificationCenter(NotificationCenterKind kind) {
 | 
			
		|||
}  // namespace
 | 
			
		||||
 | 
			
		||||
void SystemPreferences::PostNotification(const std::string& name,
 | 
			
		||||
                                         base::DictionaryValue user_info,
 | 
			
		||||
                                         base::Value::Dict user_info,
 | 
			
		||||
                                         gin::Arguments* args) {
 | 
			
		||||
  bool immediate = false;
 | 
			
		||||
  args->GetNext(&immediate);
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ void SystemPreferences::PostNotification(const std::string& name,
 | 
			
		|||
  [center
 | 
			
		||||
      postNotificationName:base::SysUTF8ToNSString(name)
 | 
			
		||||
                    object:nil
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(user_info.GetDict())
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(std::move(user_info))
 | 
			
		||||
        deliverImmediately:immediate];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -166,12 +166,12 @@ void SystemPreferences::UnsubscribeNotification(int request_id) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void SystemPreferences::PostLocalNotification(const std::string& name,
 | 
			
		||||
                                              base::DictionaryValue user_info) {
 | 
			
		||||
                                              base::Value::Dict user_info) {
 | 
			
		||||
  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
 | 
			
		||||
  [center
 | 
			
		||||
      postNotificationName:base::SysUTF8ToNSString(name)
 | 
			
		||||
                    object:nil
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(user_info.GetDict())];
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(std::move(user_info))];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SystemPreferences::SubscribeLocalNotification(
 | 
			
		||||
| 
						 | 
				
			
			@ -186,15 +186,14 @@ void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
 | 
			
		|||
                            NotificationCenterKind::kNSNotificationCenter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemPreferences::PostWorkspaceNotification(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    base::DictionaryValue user_info) {
 | 
			
		||||
void SystemPreferences::PostWorkspaceNotification(const std::string& name,
 | 
			
		||||
                                                  base::Value::Dict user_info) {
 | 
			
		||||
  NSNotificationCenter* center =
 | 
			
		||||
      [[NSWorkspace sharedWorkspace] notificationCenter];
 | 
			
		||||
  [center
 | 
			
		||||
      postNotificationName:base::SysUTF8ToNSString(name)
 | 
			
		||||
                    object:nil
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(user_info.GetDict())];
 | 
			
		||||
                  userInfo:DictionaryValueToNSDictionary(std::move(user_info))];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SystemPreferences::SubscribeWorkspaceNotification(
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +245,7 @@ int SystemPreferences::DoSubscribeNotification(
 | 
			
		|||
                } else {
 | 
			
		||||
                  copied_callback.Run(
 | 
			
		||||
                      base::SysNSStringToUTF8(notification.name),
 | 
			
		||||
                      base::DictionaryValue(), object);
 | 
			
		||||
                      base::Value(base::Value::Dict()), object);
 | 
			
		||||
                }
 | 
			
		||||
              }];
 | 
			
		||||
  return request_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -295,13 +294,14 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void SystemPreferences::RegisterDefaults(gin::Arguments* args) {
 | 
			
		||||
  base::DictionaryValue value;
 | 
			
		||||
  base::Value::Dict value;
 | 
			
		||||
 | 
			
		||||
  if (!args->GetNext(&value)) {
 | 
			
		||||
    args->ThrowError();
 | 
			
		||||
  } else {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  @try {
 | 
			
		||||
      NSDictionary* dict = DictionaryValueToNSDictionary(value.GetDict());
 | 
			
		||||
    NSDictionary* dict = DictionaryValueToNSDictionary(std::move(value));
 | 
			
		||||
    for (id key in dict) {
 | 
			
		||||
      id value = [dict objectForKey:key];
 | 
			
		||||
      if ([value isKindOfClass:[NSNull class]] || value == nil) {
 | 
			
		||||
| 
						 | 
				
			
			@ -313,7 +313,6 @@ void SystemPreferences::RegisterDefaults(gin::Arguments* args) {
 | 
			
		|||
  } @catch (NSException* exception) {
 | 
			
		||||
    args->ThrowError();
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemPreferences::SetUserDefault(const std::string& name,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,7 +165,7 @@ class Browser : public WindowListObserver {
 | 
			
		|||
 | 
			
		||||
  // Creates an activity and sets it as the one currently in use.
 | 
			
		||||
  void SetUserActivity(const std::string& type,
 | 
			
		||||
                       base::DictionaryValue user_info,
 | 
			
		||||
                       base::Value::Dict user_info,
 | 
			
		||||
                       gin::Arguments* args);
 | 
			
		||||
 | 
			
		||||
  // Returns the type name of the current user activity.
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ class Browser : public WindowListObserver {
 | 
			
		|||
 | 
			
		||||
  // Updates the current user activity
 | 
			
		||||
  void UpdateCurrentActivity(const std::string& type,
 | 
			
		||||
                             base::DictionaryValue user_info);
 | 
			
		||||
                             base::Value::Dict user_info);
 | 
			
		||||
 | 
			
		||||
  // Indicates that an user activity is about to be resumed.
 | 
			
		||||
  bool WillContinueUserActivity(const std::string& type);
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ class Browser : public WindowListObserver {
 | 
			
		|||
#endif  // BUILDFLAG(IS_MAC)
 | 
			
		||||
 | 
			
		||||
  void ShowAboutPanel();
 | 
			
		||||
  void SetAboutPanelOptions(base::DictionaryValue options);
 | 
			
		||||
  void SetAboutPanelOptions(base::Value::Dict options);
 | 
			
		||||
 | 
			
		||||
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 | 
			
		||||
  void ShowEmojiPanel();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -224,8 +224,8 @@ void Browser::ShowAboutPanel() {
 | 
			
		|||
  gtk_widget_destroy(dialogWidget);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::DictionaryValue options) {
 | 
			
		||||
  about_panel_options_ = std::move(options);
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::Value::Dict options) {
 | 
			
		||||
  about_panel_options_ = base::Value(std::move(options));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace electron
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -235,14 +235,14 @@ bool Browser::SetBadgeCount(absl::optional<int> count) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Browser::SetUserActivity(const std::string& type,
 | 
			
		||||
                              base::DictionaryValue user_info,
 | 
			
		||||
                              base::Value::Dict user_info,
 | 
			
		||||
                              gin::Arguments* args) {
 | 
			
		||||
  std::string url_string;
 | 
			
		||||
  args->GetNext(&url_string);
 | 
			
		||||
 | 
			
		||||
  [[AtomApplication sharedApplication]
 | 
			
		||||
      setCurrentActivity:base::SysUTF8ToNSString(type)
 | 
			
		||||
            withUserInfo:DictionaryValueToNSDictionary(user_info.GetDict())
 | 
			
		||||
            withUserInfo:DictionaryValueToNSDictionary(std::move(user_info))
 | 
			
		||||
          withWebpageURL:net::NSURLWithGURL(GURL(url_string))];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -261,10 +261,11 @@ void Browser::ResignCurrentActivity() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Browser::UpdateCurrentActivity(const std::string& type,
 | 
			
		||||
                                    base::DictionaryValue user_info) {
 | 
			
		||||
                                    base::Value::Dict user_info) {
 | 
			
		||||
  [[AtomApplication sharedApplication]
 | 
			
		||||
      updateCurrentActivity:base::SysUTF8ToNSString(type)
 | 
			
		||||
               withUserInfo:DictionaryValueToNSDictionary(user_info.GetDict())];
 | 
			
		||||
               withUserInfo:DictionaryValueToNSDictionary(
 | 
			
		||||
                                std::move(user_info))];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Browser::WillContinueUserActivity(const std::string& type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -511,11 +512,11 @@ void Browser::ShowAboutPanel() {
 | 
			
		|||
      orderFrontStandardAboutPanelWithOptions:options];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::DictionaryValue options) {
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::Value::Dict options) {
 | 
			
		||||
  about_panel_options_.DictClear();
 | 
			
		||||
 | 
			
		||||
  for (const auto pair : options.DictItems()) {
 | 
			
		||||
    std::string key = std::string(pair.first);
 | 
			
		||||
  for (const auto pair : options) {
 | 
			
		||||
    std::string key = pair.first;
 | 
			
		||||
    if (!key.empty() && pair.second.is_string()) {
 | 
			
		||||
      key[0] = base::ToUpperASCII(key[0]);
 | 
			
		||||
      auto val = std::make_unique<base::Value>(pair.second.Clone());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -851,8 +851,8 @@ void Browser::ShowAboutPanel() {
 | 
			
		|||
  electron::ShowMessageBoxSync(settings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::DictionaryValue options) {
 | 
			
		||||
  about_panel_options_ = std::move(options);
 | 
			
		||||
void Browser::SetAboutPanelOptions(base::Value::Dict options) {
 | 
			
		||||
  about_panel_options_ = base::Value(std::move(options));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace electron
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ ElectronBrowserContext::browser_context_map() {
 | 
			
		|||
 | 
			
		||||
ElectronBrowserContext::ElectronBrowserContext(const std::string& partition,
 | 
			
		||||
                                               bool in_memory,
 | 
			
		||||
                                               base::DictionaryValue options)
 | 
			
		||||
                                               base::Value::Dict options)
 | 
			
		||||
    : storage_policy_(base::MakeRefCounted<SpecialStoragePolicy>()),
 | 
			
		||||
      protocol_registry_(base::WrapUnique(new ProtocolRegistry)),
 | 
			
		||||
      in_memory_(in_memory),
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +111,7 @@ ElectronBrowserContext::ElectronBrowserContext(const std::string& partition,
 | 
			
		|||
  // Read options.
 | 
			
		||||
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 | 
			
		||||
  use_cache_ = !command_line->HasSwitch(switches::kDisableHttpCache);
 | 
			
		||||
  if (auto use_cache_opt = options.FindBoolKey("cache")) {
 | 
			
		||||
  if (auto use_cache_opt = options.FindBool("cache")) {
 | 
			
		||||
    use_cache_ = use_cache_opt.value();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -530,7 +530,7 @@ bool ElectronBrowserContext::CheckDevicePermission(
 | 
			
		|||
ElectronBrowserContext* ElectronBrowserContext::From(
 | 
			
		||||
    const std::string& partition,
 | 
			
		||||
    bool in_memory,
 | 
			
		||||
    base::DictionaryValue options) {
 | 
			
		||||
    base::Value::Dict options) {
 | 
			
		||||
  PartitionKey key(partition, in_memory);
 | 
			
		||||
  ElectronBrowserContext* browser_context = browser_context_map()[key].get();
 | 
			
		||||
  if (browser_context) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,6 @@ using DevicePermissionMap =
 | 
			
		|||
    std::map<blink::PermissionType,
 | 
			
		||||
             std::map<url::Origin, std::vector<std::unique_ptr<base::Value>>>>;
 | 
			
		||||
 | 
			
		||||
class ElectronBrowserContext;
 | 
			
		||||
class ElectronDownloadManagerDelegate;
 | 
			
		||||
class ElectronPermissionManager;
 | 
			
		||||
class CookieChangeNotifier;
 | 
			
		||||
| 
						 | 
				
			
			@ -82,10 +81,9 @@ class ElectronBrowserContext : public content::BrowserContext {
 | 
			
		|||
  // Get or create the BrowserContext according to its |partition| and
 | 
			
		||||
  // |in_memory|. The |options| will be passed to constructor when there is no
 | 
			
		||||
  // existing BrowserContext.
 | 
			
		||||
  static ElectronBrowserContext* From(
 | 
			
		||||
      const std::string& partition,
 | 
			
		||||
  static ElectronBrowserContext* From(const std::string& partition,
 | 
			
		||||
                                      bool in_memory,
 | 
			
		||||
      base::DictionaryValue options = base::DictionaryValue());
 | 
			
		||||
                                      base::Value::Dict options = {});
 | 
			
		||||
 | 
			
		||||
  static BrowserContextMap& browser_context_map();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +175,7 @@ class ElectronBrowserContext : public content::BrowserContext {
 | 
			
		|||
 private:
 | 
			
		||||
  ElectronBrowserContext(const std::string& partition,
 | 
			
		||||
                         bool in_memory,
 | 
			
		||||
                         base::DictionaryValue options);
 | 
			
		||||
                         base::Value::Dict options);
 | 
			
		||||
 | 
			
		||||
  // Initialize pref registry.
 | 
			
		||||
  void InitPrefs();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -658,9 +658,8 @@ void NativeWindow::NotifyWindowExecuteAppCommand(const std::string& command) {
 | 
			
		|||
    observer.OnExecuteAppCommand(command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NativeWindow::NotifyTouchBarItemInteraction(
 | 
			
		||||
    const std::string& item_id,
 | 
			
		||||
    const base::DictionaryValue& details) {
 | 
			
		||||
void NativeWindow::NotifyTouchBarItemInteraction(const std::string& item_id,
 | 
			
		||||
                                                 base::Value::Dict details) {
 | 
			
		||||
  for (NativeWindowObserver& observer : observers_)
 | 
			
		||||
    observer.OnTouchBarItemResult(item_id, details);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -304,7 +304,7 @@ class NativeWindow : public base::SupportsUserData,
 | 
			
		|||
  void NotifyWindowAlwaysOnTopChanged();
 | 
			
		||||
  void NotifyWindowExecuteAppCommand(const std::string& command);
 | 
			
		||||
  void NotifyTouchBarItemInteraction(const std::string& item_id,
 | 
			
		||||
                                     const base::DictionaryValue& details);
 | 
			
		||||
                                     base::Value::Dict details);
 | 
			
		||||
  void NotifyNewWindowForTab();
 | 
			
		||||
  void NotifyWindowSystemContextMenu(int x, int y, bool* prevent_default);
 | 
			
		||||
  void NotifyLayoutWindowControlsOverlay();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ class NativeWindowObserver : public base::CheckedObserver {
 | 
			
		|||
  virtual void OnWindowLeaveHtmlFullScreen() {}
 | 
			
		||||
  virtual void OnWindowAlwaysOnTopChanged() {}
 | 
			
		||||
  virtual void OnTouchBarItemResult(const std::string& item_id,
 | 
			
		||||
                                    const base::DictionaryValue& details) {}
 | 
			
		||||
                                    const base::Value::Dict& details) {}
 | 
			
		||||
  virtual void OnNewWindowForTab() {}
 | 
			
		||||
  virtual void OnSystemContextMenu(int x, int y, bool* prevent_default) {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,9 +114,9 @@ network::mojom::URLResponseHeadPtr ToResponseHead(
 | 
			
		|||
  bool has_mime_type = dict.Get("mimeType", &head->mime_type);
 | 
			
		||||
  bool has_content_type = false;
 | 
			
		||||
 | 
			
		||||
  base::DictionaryValue headers;
 | 
			
		||||
  base::Value::Dict headers;
 | 
			
		||||
  if (dict.Get("headers", &headers)) {
 | 
			
		||||
    for (const auto iter : headers.DictItems()) {
 | 
			
		||||
    for (const auto iter : headers) {
 | 
			
		||||
      if (iter.second.is_string()) {
 | 
			
		||||
        // key, value
 | 
			
		||||
        head->headers->AddHeader(iter.first, iter.second.GetString());
 | 
			
		||||
| 
						 | 
				
			
			@ -513,7 +513,7 @@ void ElectronURLLoaderFactory::StartLoadingHttp(
 | 
			
		|||
  if (!dict.Get("method", &request->method))
 | 
			
		||||
    request->method = original_request.method;
 | 
			
		||||
 | 
			
		||||
  base::DictionaryValue upload_data;
 | 
			
		||||
  base::Value::Dict upload_data;
 | 
			
		||||
  if (request->method != net::HttpRequestHeaders::kGetMethod &&
 | 
			
		||||
      request->method != net::HttpRequestHeaders::kHeadMethod)
 | 
			
		||||
    dict.Get("uploadData", &upload_data);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ URLPipeLoader::URLPipeLoader(
 | 
			
		|||
    mojo::PendingReceiver<network::mojom::URLLoader> loader,
 | 
			
		||||
    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
 | 
			
		||||
    const net::NetworkTrafficAnnotationTag& annotation,
 | 
			
		||||
    base::DictionaryValue upload_data)
 | 
			
		||||
    base::Value::Dict upload_data)
 | 
			
		||||
    : url_loader_(this, std::move(loader)), client_(std::move(client)) {
 | 
			
		||||
  url_loader_.set_disconnect_handler(base::BindOnce(
 | 
			
		||||
      &URLPipeLoader::NotifyComplete, base::Unretained(this), net::ERR_FAILED));
 | 
			
		||||
| 
						 | 
				
			
			@ -37,17 +37,17 @@ void URLPipeLoader::Start(
 | 
			
		|||
    scoped_refptr<network::SharedURLLoaderFactory> factory,
 | 
			
		||||
    std::unique_ptr<network::ResourceRequest> request,
 | 
			
		||||
    const net::NetworkTrafficAnnotationTag& annotation,
 | 
			
		||||
    base::DictionaryValue upload_data) {
 | 
			
		||||
    base::Value::Dict upload_data) {
 | 
			
		||||
  loader_ = network::SimpleURLLoader::Create(std::move(request), annotation);
 | 
			
		||||
  loader_->SetOnResponseStartedCallback(base::BindOnce(
 | 
			
		||||
      &URLPipeLoader::OnResponseStarted, weak_factory_.GetWeakPtr()));
 | 
			
		||||
 | 
			
		||||
  // TODO(zcbenz): The old protocol API only supports string as upload data,
 | 
			
		||||
  // we should seek to support more types in future.
 | 
			
		||||
  std::string content_type, data;
 | 
			
		||||
  if (upload_data.GetString("contentType", &content_type) &&
 | 
			
		||||
      upload_data.GetString("data", &data))
 | 
			
		||||
    loader_->AttachStringForUpload(data, content_type);
 | 
			
		||||
  std::string* content_type = upload_data.FindString("contentType");
 | 
			
		||||
  std::string* data = upload_data.FindString("data");
 | 
			
		||||
  if (content_type && data)
 | 
			
		||||
    loader_->AttachStringForUpload(*data, *content_type);
 | 
			
		||||
 | 
			
		||||
  loader_->DownloadAsStream(factory.get(), this);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ class URLPipeLoader : public network::mojom::URLLoader,
 | 
			
		|||
                mojo::PendingReceiver<network::mojom::URLLoader> loader,
 | 
			
		||||
                mojo::PendingRemote<network::mojom::URLLoaderClient> client,
 | 
			
		||||
                const net::NetworkTrafficAnnotationTag& annotation,
 | 
			
		||||
                base::DictionaryValue upload_data);
 | 
			
		||||
                base::Value::Dict upload_data);
 | 
			
		||||
 | 
			
		||||
  // disable copy
 | 
			
		||||
  URLPipeLoader(const URLPipeLoader&) = delete;
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,7 @@ class URLPipeLoader : public network::mojom::URLLoader,
 | 
			
		|||
  void Start(scoped_refptr<network::SharedURLLoaderFactory> factory,
 | 
			
		||||
             std::unique_ptr<network::ResourceRequest> request,
 | 
			
		||||
             const net::NetworkTrafficAnnotationTag& annotation,
 | 
			
		||||
             base::DictionaryValue upload_data);
 | 
			
		||||
             base::Value::Dict upload_data);
 | 
			
		||||
  void NotifyComplete(int result);
 | 
			
		||||
  void OnResponseStarted(const GURL& final_url,
 | 
			
		||||
                         const network::mojom::URLResponseHead& response_head);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -241,8 +241,7 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
 | 
			
		|||
- (void)buttonAction:(id)sender {
 | 
			
		||||
  NSString* item_id =
 | 
			
		||||
      [NSString stringWithFormat:@"%ld", ((NSButton*)sender).tag];
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String],
 | 
			
		||||
                                         base::DictionaryValue());
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String], {});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)colorPickerAction:(id)sender {
 | 
			
		||||
| 
						 | 
				
			
			@ -252,19 +251,20 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
 | 
			
		|||
  NSColor* color = ((NSColorPickerTouchBarItem*)sender).color;
 | 
			
		||||
  std::string hex_color =
 | 
			
		||||
      electron::ToRGBHex(skia::NSDeviceColorToSkColor(color));
 | 
			
		||||
  base::DictionaryValue details;
 | 
			
		||||
  details.SetString("color", hex_color);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
 | 
			
		||||
  base::Value::Dict details;
 | 
			
		||||
  details.Set("color", hex_color);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String],
 | 
			
		||||
                                         std::move(details));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)sliderAction:(id)sender {
 | 
			
		||||
  NSString* identifier = ((NSSliderTouchBarItem*)sender).identifier;
 | 
			
		||||
  NSString* item_id = [self idFromIdentifier:identifier
 | 
			
		||||
                                  withPrefix:SliderIdentifier];
 | 
			
		||||
  base::DictionaryValue details;
 | 
			
		||||
  details.SetInteger("value",
 | 
			
		||||
                     [((NSSliderTouchBarItem*)sender).slider intValue]);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
 | 
			
		||||
  base::Value::Dict details;
 | 
			
		||||
  details.Set("value", [((NSSliderTouchBarItem*)sender).slider intValue]);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String],
 | 
			
		||||
                                         std::move(details));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSString*)idFromIdentifier:(NSString*)identifier
 | 
			
		||||
| 
						 | 
				
			
			@ -275,32 +275,33 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
 | 
			
		|||
- (void)segmentedControlAction:(id)sender {
 | 
			
		||||
  NSString* item_id =
 | 
			
		||||
      [NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
 | 
			
		||||
  base::DictionaryValue details;
 | 
			
		||||
  details.SetInteger("selectedIndex",
 | 
			
		||||
                     ((NSSegmentedControl*)sender).selectedSegment);
 | 
			
		||||
  details.SetBoolean(
 | 
			
		||||
  base::Value::Dict details;
 | 
			
		||||
  details.Set("selectedIndex",
 | 
			
		||||
              static_cast<int>(((NSSegmentedControl*)sender).selectedSegment));
 | 
			
		||||
  details.Set(
 | 
			
		||||
      "isSelected",
 | 
			
		||||
      [((NSSegmentedControl*)sender)
 | 
			
		||||
          isSelectedForSegment:((NSSegmentedControl*)sender).selectedSegment]);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([item_id UTF8String],
 | 
			
		||||
                                         std::move(details));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)scrubber:(NSScrubber*)scrubber
 | 
			
		||||
    didSelectItemAtIndex:(NSInteger)selectedIndex {
 | 
			
		||||
  base::DictionaryValue details;
 | 
			
		||||
  details.SetInteger("selectedIndex", selectedIndex);
 | 
			
		||||
  details.SetString("type", "select");
 | 
			
		||||
  base::Value::Dict details;
 | 
			
		||||
  details.Set("selectedIndex", static_cast<int>(selectedIndex));
 | 
			
		||||
  details.Set("type", "select");
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String],
 | 
			
		||||
                                         details);
 | 
			
		||||
                                         std::move(details));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)scrubber:(NSScrubber*)scrubber
 | 
			
		||||
    didHighlightItemAtIndex:(NSInteger)highlightedIndex {
 | 
			
		||||
  base::DictionaryValue details;
 | 
			
		||||
  details.SetInteger("highlightedIndex", highlightedIndex);
 | 
			
		||||
  details.SetString("type", "highlight");
 | 
			
		||||
  base::Value::Dict details;
 | 
			
		||||
  details.Set("highlightedIndex", static_cast<int>(highlightedIndex));
 | 
			
		||||
  details.Set("type", "highlight");
 | 
			
		||||
  window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String],
 | 
			
		||||
                                         details);
 | 
			
		||||
                                         std::move(details));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -329,24 +329,24 @@ float NativeImage::GetAspectRatio(const absl::optional<float> scale_factor) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
gin::Handle<NativeImage> NativeImage::Resize(gin::Arguments* args,
 | 
			
		||||
                                             base::DictionaryValue options) {
 | 
			
		||||
                                             base::Value::Dict options) {
 | 
			
		||||
  float scale_factor = GetScaleFactorFromOptions(args);
 | 
			
		||||
 | 
			
		||||
  gfx::Size size = GetSize(scale_factor);
 | 
			
		||||
  int width = size.width();
 | 
			
		||||
  int height = size.height();
 | 
			
		||||
  bool width_set = options.GetInteger("width", &width);
 | 
			
		||||
  bool height_set = options.GetInteger("height", &height);
 | 
			
		||||
  absl::optional<int> new_width = options.FindInt("width");
 | 
			
		||||
  absl::optional<int> new_height = options.FindInt("height");
 | 
			
		||||
  int width = new_width.value_or(size.width());
 | 
			
		||||
  int height = new_height.value_or(size.height());
 | 
			
		||||
  size.SetSize(width, height);
 | 
			
		||||
 | 
			
		||||
  if (width <= 0 && height <= 0) {
 | 
			
		||||
    return CreateEmpty(args->isolate());
 | 
			
		||||
  } else if (width_set && !height_set) {
 | 
			
		||||
  } else if (new_width && !new_height) {
 | 
			
		||||
    // Scale height to preserve original aspect ratio
 | 
			
		||||
    size.set_height(width);
 | 
			
		||||
    size =
 | 
			
		||||
        gfx::ScaleToRoundedSize(size, 1.f, 1.f / GetAspectRatio(scale_factor));
 | 
			
		||||
  } else if (height_set && !width_set) {
 | 
			
		||||
  } else if (new_height && !new_width) {
 | 
			
		||||
    // Scale width to preserve original aspect ratio
 | 
			
		||||
    size.set_width(height);
 | 
			
		||||
    size = gfx::ScaleToRoundedSize(size, GetAspectRatio(scale_factor), 1.f);
 | 
			
		||||
| 
						 | 
				
			
			@ -354,11 +354,10 @@ gin::Handle<NativeImage> NativeImage::Resize(gin::Arguments* args,
 | 
			
		|||
 | 
			
		||||
  skia::ImageOperations::ResizeMethod method =
 | 
			
		||||
      skia::ImageOperations::ResizeMethod::RESIZE_BEST;
 | 
			
		||||
  std::string quality;
 | 
			
		||||
  options.GetString("quality", &quality);
 | 
			
		||||
  if (quality == "good")
 | 
			
		||||
  std::string* quality = options.FindString("quality");
 | 
			
		||||
  if (quality && *quality == "good")
 | 
			
		||||
    method = skia::ImageOperations::ResizeMethod::RESIZE_GOOD;
 | 
			
		||||
  else if (quality == "better")
 | 
			
		||||
  else if (quality && *quality == "better")
 | 
			
		||||
    method = skia::ImageOperations::ResizeMethod::RESIZE_BETTER;
 | 
			
		||||
 | 
			
		||||
  gfx::ImageSkia resized = gfx::ImageSkiaOperations::CreateResizedImage(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ class NativeImage : public gin::Wrappable<NativeImage> {
 | 
			
		|||
  v8::Local<v8::Value> GetBitmap(gin::Arguments* args);
 | 
			
		||||
  v8::Local<v8::Value> GetNativeHandle(gin_helper::ErrorThrower thrower);
 | 
			
		||||
  gin::Handle<NativeImage> Resize(gin::Arguments* args,
 | 
			
		||||
                                  base::DictionaryValue options);
 | 
			
		||||
                                  base::Value::Dict options);
 | 
			
		||||
  gin::Handle<NativeImage> Crop(v8::Isolate* isolate, const gfx::Rect& rect);
 | 
			
		||||
  std::string ToDataURL(gin::Arguments* args);
 | 
			
		||||
  bool IsEmpty();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,8 @@ v8::Local<v8::Value> Converter<const extensions::Extension*>::ToV8(
 | 
			
		|||
  dict.Set("path", extension->path());
 | 
			
		||||
  dict.Set("url", extension->url());
 | 
			
		||||
  dict.Set("version", extension->VersionString());
 | 
			
		||||
  dict.Set("manifest", *(extension->manifest()->value()));
 | 
			
		||||
  dict.Set("manifest",
 | 
			
		||||
           *static_cast<const base::Value*>(extension->manifest()->value()));
 | 
			
		||||
 | 
			
		||||
  return gin::ConvertToV8(isolate, dict);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -234,13 +234,13 @@ v8::Local<v8::Value> Converter<net::HttpRequestHeaders>::ToV8(
 | 
			
		|||
bool Converter<net::HttpRequestHeaders>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
                                                v8::Local<v8::Value> val,
 | 
			
		||||
                                                net::HttpRequestHeaders* out) {
 | 
			
		||||
  base::DictionaryValue dict;
 | 
			
		||||
  base::Value::Dict dict;
 | 
			
		||||
  if (!ConvertFromV8(isolate, val, &dict))
 | 
			
		||||
    return false;
 | 
			
		||||
  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
 | 
			
		||||
    if (it.value().is_string()) {
 | 
			
		||||
      std::string value = it.value().GetString();
 | 
			
		||||
      out->SetHeader(it.key(), value);
 | 
			
		||||
  for (const auto it : dict) {
 | 
			
		||||
    if (it.second.is_string()) {
 | 
			
		||||
      std::string value = it.second.GetString();
 | 
			
		||||
      out->SetHeader(it.first, value);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,38 +7,38 @@
 | 
			
		|||
#include <memory>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include "base/values.h"
 | 
			
		||||
#include "shell/common/v8_value_converter.h"
 | 
			
		||||
#include "content/public/renderer/v8_value_converter.h"
 | 
			
		||||
 | 
			
		||||
namespace gin {
 | 
			
		||||
 | 
			
		||||
bool Converter<base::DictionaryValue>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
bool Converter<base::Value::Dict>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
                                          v8::Local<v8::Value> val,
 | 
			
		||||
                                              base::DictionaryValue* out) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  std::unique_ptr<base::Value> value(
 | 
			
		||||
      converter.FromV8Value(val, isolate->GetCurrentContext()));
 | 
			
		||||
                                          base::Value::Dict* out) {
 | 
			
		||||
  std::unique_ptr<base::Value> value =
 | 
			
		||||
      content::V8ValueConverter::Create()->FromV8Value(
 | 
			
		||||
          val, isolate->GetCurrentContext());
 | 
			
		||||
  if (value && value->is_dict()) {
 | 
			
		||||
    out->Swap(static_cast<base::DictionaryValue*>(value.get()));
 | 
			
		||||
    *out = std::move(value->GetDict());
 | 
			
		||||
    return true;
 | 
			
		||||
  } else {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> Converter<base::DictionaryValue>::ToV8(
 | 
			
		||||
v8::Local<v8::Value> Converter<base::Value::Dict>::ToV8(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::DictionaryValue& val) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  return converter.ToV8Value(&val, isolate->GetCurrentContext());
 | 
			
		||||
    const base::Value::Dict& val) {
 | 
			
		||||
  base::Value value(val.Clone());
 | 
			
		||||
  return content::V8ValueConverter::Create()->ToV8Value(
 | 
			
		||||
      &value, isolate->GetCurrentContext());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Converter<base::Value>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
                                    v8::Local<v8::Value> val,
 | 
			
		||||
                                    base::Value* out) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  std::unique_ptr<base::Value> value(
 | 
			
		||||
      converter.FromV8Value(val, isolate->GetCurrentContext()));
 | 
			
		||||
  std::unique_ptr<base::Value> value =
 | 
			
		||||
      content::V8ValueConverter::Create()->FromV8Value(
 | 
			
		||||
          val, isolate->GetCurrentContext());
 | 
			
		||||
  if (value) {
 | 
			
		||||
    *out = std::move(*value);
 | 
			
		||||
    return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,29 +49,30 @@ bool Converter<base::Value>::FromV8(v8::Isolate* isolate,
 | 
			
		|||
 | 
			
		||||
v8::Local<v8::Value> Converter<base::Value>::ToV8(v8::Isolate* isolate,
 | 
			
		||||
                                                  const base::Value& val) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  return converter.ToV8Value(&val, isolate->GetCurrentContext());
 | 
			
		||||
  return content::V8ValueConverter::Create()->ToV8Value(
 | 
			
		||||
      &val, isolate->GetCurrentContext());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
bool Converter<base::Value::List>::FromV8(v8::Isolate* isolate,
 | 
			
		||||
                                          v8::Local<v8::Value> val,
 | 
			
		||||
                                        base::ListValue* out) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  std::unique_ptr<base::Value> value(
 | 
			
		||||
      converter.FromV8Value(val, isolate->GetCurrentContext()));
 | 
			
		||||
                                          base::Value::List* out) {
 | 
			
		||||
  std::unique_ptr<base::Value> value =
 | 
			
		||||
      content::V8ValueConverter::Create()->FromV8Value(
 | 
			
		||||
          val, isolate->GetCurrentContext());
 | 
			
		||||
  if (value && value->is_list()) {
 | 
			
		||||
    out->Swap(static_cast<base::ListValue*>(value.get()));
 | 
			
		||||
    *out = std::move(value->GetList());
 | 
			
		||||
    return true;
 | 
			
		||||
  } else {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> Converter<base::ListValue>::ToV8(
 | 
			
		||||
v8::Local<v8::Value> Converter<base::Value::List>::ToV8(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::ListValue& val) {
 | 
			
		||||
  electron::V8ValueConverter converter;
 | 
			
		||||
  return converter.ToV8Value(&val, isolate->GetCurrentContext());
 | 
			
		||||
    const base::Value::List& val) {
 | 
			
		||||
  base::Value value(val.Clone());
 | 
			
		||||
  return content::V8ValueConverter::Create()->ToV8Value(
 | 
			
		||||
      &value, isolate->GetCurrentContext());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace gin
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,23 +5,18 @@
 | 
			
		|||
#ifndef ELECTRON_SHELL_COMMON_GIN_CONVERTERS_VALUE_CONVERTER_H_
 | 
			
		||||
#define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_VALUE_CONVERTER_H_
 | 
			
		||||
 | 
			
		||||
#include "base/values.h"
 | 
			
		||||
#include "gin/converter.h"
 | 
			
		||||
 | 
			
		||||
namespace base {
 | 
			
		||||
class DictionaryValue;
 | 
			
		||||
class ListValue;
 | 
			
		||||
class Value;
 | 
			
		||||
}  // namespace base
 | 
			
		||||
 | 
			
		||||
namespace gin {
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct Converter<base::DictionaryValue> {
 | 
			
		||||
struct Converter<base::Value::Dict> {
 | 
			
		||||
  static bool FromV8(v8::Isolate* isolate,
 | 
			
		||||
                     v8::Local<v8::Value> val,
 | 
			
		||||
                     base::DictionaryValue* out);
 | 
			
		||||
                     base::Value::Dict* out);
 | 
			
		||||
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
 | 
			
		||||
                                   const base::DictionaryValue& val);
 | 
			
		||||
                                   const base::Value::Dict& val);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
| 
						 | 
				
			
			@ -34,12 +29,12 @@ struct Converter<base::Value> {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct Converter<base::ListValue> {
 | 
			
		||||
struct Converter<base::Value::List> {
 | 
			
		||||
  static bool FromV8(v8::Isolate* isolate,
 | 
			
		||||
                     v8::Local<v8::Value> val,
 | 
			
		||||
                     base::ListValue* out);
 | 
			
		||||
                     base::Value::List* out);
 | 
			
		||||
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
 | 
			
		||||
                                   const base::ListValue& val);
 | 
			
		||||
                                   const base::Value::List& val);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace gin
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,524 +0,0 @@
 | 
			
		|||
// Copyright (c) 2013 GitHub, Inc.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "shell/common/v8_value_converter.h"
 | 
			
		||||
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "base/logging.h"
 | 
			
		||||
#include "base/values.h"
 | 
			
		||||
#include "shell/common/gin_helper/dictionary.h"
 | 
			
		||||
#include "shell/common/node_bindings.h"
 | 
			
		||||
#include "shell/common/node_includes.h"
 | 
			
		||||
 | 
			
		||||
namespace electron {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
const int kMaxRecursionDepth = 100;
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
// The state of a call to FromV8Value.
 | 
			
		||||
class V8ValueConverter::FromV8ValueState {
 | 
			
		||||
 public:
 | 
			
		||||
  // Level scope which updates the current depth of some FromV8ValueState.
 | 
			
		||||
  class Level {
 | 
			
		||||
   public:
 | 
			
		||||
    explicit Level(FromV8ValueState* state) : state_(state) {
 | 
			
		||||
      state_->max_recursion_depth_--;
 | 
			
		||||
    }
 | 
			
		||||
    ~Level() { state_->max_recursion_depth_++; }
 | 
			
		||||
 | 
			
		||||
   private:
 | 
			
		||||
    FromV8ValueState* state_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  FromV8ValueState() : max_recursion_depth_(kMaxRecursionDepth) {}
 | 
			
		||||
 | 
			
		||||
  // If |handle| is not in |unique_map_|, then add it to |unique_map_| and
 | 
			
		||||
  // return true.
 | 
			
		||||
  //
 | 
			
		||||
  // Otherwise do nothing and return false. Here "A is unique" means that no
 | 
			
		||||
  // other handle B in the map points to the same object as A. Note that A can
 | 
			
		||||
  // be unique even if there already is another handle with the same identity
 | 
			
		||||
  // hash (key) in the map, because two objects can have the same hash.
 | 
			
		||||
  bool AddToUniquenessCheck(v8::Local<v8::Object> handle) {
 | 
			
		||||
    int hash;
 | 
			
		||||
    auto iter = GetIteratorInMap(handle, &hash);
 | 
			
		||||
    if (iter != unique_map_.end())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    unique_map_.insert(std::make_pair(hash, handle));
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool RemoveFromUniquenessCheck(v8::Local<v8::Object> handle) {
 | 
			
		||||
    int unused_hash;
 | 
			
		||||
    auto iter = GetIteratorInMap(handle, &unused_hash);
 | 
			
		||||
    if (iter == unique_map_.end())
 | 
			
		||||
      return false;
 | 
			
		||||
    unique_map_.erase(iter);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool HasReachedMaxRecursionDepth() { return max_recursion_depth_ < 0; }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  using HashToHandleMap = std::multimap<int, v8::Local<v8::Object>>;
 | 
			
		||||
  using Iterator = HashToHandleMap::const_iterator;
 | 
			
		||||
 | 
			
		||||
  Iterator GetIteratorInMap(v8::Local<v8::Object> handle, int* hash) {
 | 
			
		||||
    *hash = handle->GetIdentityHash();
 | 
			
		||||
    // We only compare using == with handles to objects with the same identity
 | 
			
		||||
    // hash. Different hash obviously means different objects, but two objects
 | 
			
		||||
    // in a couple of thousands could have the same identity hash.
 | 
			
		||||
    std::pair<Iterator, Iterator> range = unique_map_.equal_range(*hash);
 | 
			
		||||
    for (auto it = range.first; it != range.second; ++it) {
 | 
			
		||||
      // Operator == for handles actually compares the underlying objects.
 | 
			
		||||
      if (it->second == handle)
 | 
			
		||||
        return it;
 | 
			
		||||
    }
 | 
			
		||||
    // Not found.
 | 
			
		||||
    return unique_map_.end();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  HashToHandleMap unique_map_;
 | 
			
		||||
 | 
			
		||||
  int max_recursion_depth_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A class to ensure that objects/arrays that are being converted by
 | 
			
		||||
// this V8ValueConverterImpl do not have cycles.
 | 
			
		||||
//
 | 
			
		||||
// An example of cycle: var v = {}; v = {key: v};
 | 
			
		||||
// Not an example of cycle: var v = {}; a = [v, v]; or w = {a: v, b: v};
 | 
			
		||||
class V8ValueConverter::ScopedUniquenessGuard {
 | 
			
		||||
 public:
 | 
			
		||||
  ScopedUniquenessGuard(V8ValueConverter::FromV8ValueState* state,
 | 
			
		||||
                        v8::Local<v8::Object> value)
 | 
			
		||||
      : state_(state),
 | 
			
		||||
        value_(value),
 | 
			
		||||
        is_valid_(state_->AddToUniquenessCheck(value_)) {}
 | 
			
		||||
  ~ScopedUniquenessGuard() {
 | 
			
		||||
    if (is_valid_) {
 | 
			
		||||
      bool removed = state_->RemoveFromUniquenessCheck(value_);
 | 
			
		||||
      DCHECK(removed);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // disable copy
 | 
			
		||||
  ScopedUniquenessGuard(const ScopedUniquenessGuard&) = delete;
 | 
			
		||||
  ScopedUniquenessGuard& operator=(const ScopedUniquenessGuard&) = delete;
 | 
			
		||||
 | 
			
		||||
  bool is_valid() const { return is_valid_; }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  typedef std::multimap<int, v8::Local<v8::Object>> HashToHandleMap;
 | 
			
		||||
  V8ValueConverter::FromV8ValueState* state_;
 | 
			
		||||
  v8::Local<v8::Object> value_;
 | 
			
		||||
  bool is_valid_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
V8ValueConverter::V8ValueConverter() = default;
 | 
			
		||||
 | 
			
		||||
void V8ValueConverter::SetRegExpAllowed(bool val) {
 | 
			
		||||
  reg_exp_allowed_ = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void V8ValueConverter::SetFunctionAllowed(bool val) {
 | 
			
		||||
  function_allowed_ = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void V8ValueConverter::SetStripNullFromObjects(bool val) {
 | 
			
		||||
  strip_null_from_objects_ = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> V8ValueConverter::ToV8Value(
 | 
			
		||||
    const base::Value* value,
 | 
			
		||||
    v8::Local<v8::Context> context) const {
 | 
			
		||||
  v8::Context::Scope context_scope(context);
 | 
			
		||||
  v8::EscapableHandleScope handle_scope(context->GetIsolate());
 | 
			
		||||
  return handle_scope.Escape(ToV8ValueImpl(context->GetIsolate(), value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<base::Value> V8ValueConverter::FromV8Value(
 | 
			
		||||
    v8::Local<v8::Value> val,
 | 
			
		||||
    v8::Local<v8::Context> context) const {
 | 
			
		||||
  v8::Context::Scope context_scope(context);
 | 
			
		||||
  v8::HandleScope handle_scope(context->GetIsolate());
 | 
			
		||||
  FromV8ValueState state;
 | 
			
		||||
  return FromV8ValueImpl(&state, val, context->GetIsolate());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::Value* value) const {
 | 
			
		||||
  switch (value->type()) {
 | 
			
		||||
    case base::Value::Type::NONE:
 | 
			
		||||
      return v8::Null(isolate);
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::BOOLEAN: {
 | 
			
		||||
      bool val = value->GetBool();
 | 
			
		||||
      return v8::Boolean::New(isolate, val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::INTEGER: {
 | 
			
		||||
      int val = value->GetInt();
 | 
			
		||||
      return v8::Integer::New(isolate, val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::DOUBLE: {
 | 
			
		||||
      double val = value->GetDouble();
 | 
			
		||||
      return v8::Number::New(isolate, val);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::STRING: {
 | 
			
		||||
      std::string val = value->GetString();
 | 
			
		||||
      return v8::String::NewFromUtf8(isolate, val.c_str(),
 | 
			
		||||
                                     v8::NewStringType::kNormal, val.length())
 | 
			
		||||
          .ToLocalChecked();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::LIST:
 | 
			
		||||
      return ToV8Array(isolate, static_cast<const base::ListValue*>(value));
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::DICTIONARY:
 | 
			
		||||
      return ToV8Object(isolate,
 | 
			
		||||
                        static_cast<const base::DictionaryValue*>(value));
 | 
			
		||||
 | 
			
		||||
    case base::Value::Type::BINARY:
 | 
			
		||||
      return ToArrayBuffer(isolate, static_cast<const base::Value*>(value));
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      LOG(ERROR) << "Unexpected value type: " << value->type();
 | 
			
		||||
      return v8::Null(isolate);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> V8ValueConverter::ToV8Array(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::ListValue* val) const {
 | 
			
		||||
  v8::Local<v8::Array> result(
 | 
			
		||||
      v8::Array::New(isolate, val->GetListDeprecated().size()));
 | 
			
		||||
  auto context = isolate->GetCurrentContext();
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; i < val->GetListDeprecated().size(); ++i) {
 | 
			
		||||
    const base::Value& child = val->GetListDeprecated()[i];
 | 
			
		||||
 | 
			
		||||
    v8::Local<v8::Value> child_v8 = ToV8ValueImpl(isolate, &child);
 | 
			
		||||
 | 
			
		||||
    v8::TryCatch try_catch(isolate);
 | 
			
		||||
    result->Set(context, static_cast<uint32_t>(i), child_v8).Check();
 | 
			
		||||
    if (try_catch.HasCaught())
 | 
			
		||||
      LOG(ERROR) << "Setter for index " << i << " threw an exception.";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> V8ValueConverter::ToV8Object(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::DictionaryValue* val) const {
 | 
			
		||||
  gin_helper::Dictionary result = gin::Dictionary::CreateEmpty(isolate);
 | 
			
		||||
  result.SetHidden("simple", true);
 | 
			
		||||
 | 
			
		||||
  for (base::DictionaryValue::Iterator iter(*val); !iter.IsAtEnd();
 | 
			
		||||
       iter.Advance()) {
 | 
			
		||||
    const std::string& key = iter.key();
 | 
			
		||||
    v8::Local<v8::Value> child_v8 = ToV8ValueImpl(isolate, &iter.value());
 | 
			
		||||
 | 
			
		||||
    v8::TryCatch try_catch(isolate);
 | 
			
		||||
    result.Set(key, child_v8);
 | 
			
		||||
    if (try_catch.HasCaught()) {
 | 
			
		||||
      LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
 | 
			
		||||
                 << "exception.";
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result.GetHandle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
v8::Local<v8::Value> V8ValueConverter::ToArrayBuffer(
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const base::Value* value) const {
 | 
			
		||||
  const auto* data = reinterpret_cast<const char*>(value->GetBlob().data());
 | 
			
		||||
  size_t length = value->GetBlob().size();
 | 
			
		||||
 | 
			
		||||
  if (NodeBindings::IsInitialized()) {
 | 
			
		||||
    return node::Buffer::Copy(isolate, data, length).ToLocalChecked();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (length > node::Buffer::kMaxLength) {
 | 
			
		||||
    return v8::Local<v8::Object>();
 | 
			
		||||
  }
 | 
			
		||||
  auto context = isolate->GetCurrentContext();
 | 
			
		||||
  auto array_buffer = v8::ArrayBuffer::New(isolate, length);
 | 
			
		||||
  std::shared_ptr<v8::BackingStore> backing_store =
 | 
			
		||||
      array_buffer->GetBackingStore();
 | 
			
		||||
  memcpy(backing_store->Data(), data, length);
 | 
			
		||||
  // From this point, if something goes wrong(can't find Buffer class for
 | 
			
		||||
  // example) we'll simply return a Uint8Array based on the created ArrayBuffer.
 | 
			
		||||
  // This can happen if no preload script was specified to the renderer.
 | 
			
		||||
  gin_helper::Dictionary global(isolate, context->Global());
 | 
			
		||||
  v8::Local<v8::Value> buffer_value;
 | 
			
		||||
 | 
			
		||||
  // Get the Buffer class stored as a hidden value in the global object. We'll
 | 
			
		||||
  // use it return a browserified Buffer.
 | 
			
		||||
  if (!global.GetHidden("Buffer", &buffer_value) ||
 | 
			
		||||
      !buffer_value->IsFunction()) {
 | 
			
		||||
    return v8::Uint8Array::New(array_buffer, 0, length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  gin::Dictionary buffer_class(
 | 
			
		||||
      isolate,
 | 
			
		||||
      buffer_value->ToObject(isolate->GetCurrentContext()).ToLocalChecked());
 | 
			
		||||
  v8::Local<v8::Value> from_value;
 | 
			
		||||
  if (!buffer_class.Get("from", &from_value) || !from_value->IsFunction()) {
 | 
			
		||||
    return v8::Uint8Array::New(array_buffer, 0, length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  v8::Local<v8::Value> args[] = {array_buffer};
 | 
			
		||||
  auto func = from_value.As<v8::Function>();
 | 
			
		||||
  auto result = func->Call(context, v8::Null(isolate), std::size(args), args);
 | 
			
		||||
  if (!result.IsEmpty()) {
 | 
			
		||||
    return result.ToLocalChecked();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return v8::Uint8Array::New(array_buffer, 0, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<base::Value> V8ValueConverter::FromV8ValueImpl(
 | 
			
		||||
    FromV8ValueState* state,
 | 
			
		||||
    v8::Local<v8::Value> val,
 | 
			
		||||
    v8::Isolate* isolate) const {
 | 
			
		||||
  FromV8ValueState::Level state_level(state);
 | 
			
		||||
  if (state->HasReachedMaxRecursionDepth())
 | 
			
		||||
    return nullptr;
 | 
			
		||||
 | 
			
		||||
  if (val->IsExternal())
 | 
			
		||||
    return std::make_unique<base::Value>();
 | 
			
		||||
 | 
			
		||||
  if (val->IsNull())
 | 
			
		||||
    return std::make_unique<base::Value>();
 | 
			
		||||
 | 
			
		||||
  auto context = isolate->GetCurrentContext();
 | 
			
		||||
 | 
			
		||||
  if (val->IsBoolean())
 | 
			
		||||
    return std::make_unique<base::Value>(val->ToBoolean(isolate)->Value());
 | 
			
		||||
 | 
			
		||||
  if (val->IsInt32())
 | 
			
		||||
    return std::make_unique<base::Value>(val.As<v8::Int32>()->Value());
 | 
			
		||||
 | 
			
		||||
  if (val->IsNumber()) {
 | 
			
		||||
    double val_as_double = val.As<v8::Number>()->Value();
 | 
			
		||||
    if (!std::isfinite(val_as_double))
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    return std::make_unique<base::Value>(val_as_double);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (val->IsString()) {
 | 
			
		||||
    v8::String::Utf8Value utf8(isolate, val);
 | 
			
		||||
    return std::make_unique<base::Value>(std::string(*utf8, utf8.length()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (val->IsUndefined())
 | 
			
		||||
    // JSON.stringify ignores undefined.
 | 
			
		||||
    return nullptr;
 | 
			
		||||
 | 
			
		||||
  if (val->IsDate()) {
 | 
			
		||||
    v8::Date* date = v8::Date::Cast(*val);
 | 
			
		||||
    v8::Local<v8::Value> toISOString =
 | 
			
		||||
        date->Get(context, v8::String::NewFromUtf8(isolate, "toISOString",
 | 
			
		||||
                                                   v8::NewStringType::kNormal)
 | 
			
		||||
                               .ToLocalChecked())
 | 
			
		||||
            .ToLocalChecked();
 | 
			
		||||
    if (toISOString->IsFunction()) {
 | 
			
		||||
      v8::MaybeLocal<v8::Value> result =
 | 
			
		||||
          toISOString.As<v8::Function>()->Call(context, val, 0, nullptr);
 | 
			
		||||
      if (!result.IsEmpty()) {
 | 
			
		||||
        v8::String::Utf8Value utf8(isolate, result.ToLocalChecked());
 | 
			
		||||
        return std::make_unique<base::Value>(std::string(*utf8, utf8.length()));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (val->IsRegExp()) {
 | 
			
		||||
    if (!reg_exp_allowed_)
 | 
			
		||||
      // JSON.stringify converts to an object.
 | 
			
		||||
      return FromV8Object(val.As<v8::Object>(), state, isolate);
 | 
			
		||||
    return std::make_unique<base::Value>(*v8::String::Utf8Value(isolate, val));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // v8::Value doesn't have a ToArray() method for some reason.
 | 
			
		||||
  if (val->IsArray())
 | 
			
		||||
    return FromV8Array(val.As<v8::Array>(), state, isolate);
 | 
			
		||||
 | 
			
		||||
  if (val->IsFunction()) {
 | 
			
		||||
    if (!function_allowed_)
 | 
			
		||||
      // JSON.stringify refuses to convert function(){}.
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    return FromV8Object(val.As<v8::Object>(), state, isolate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (node::Buffer::HasInstance(val)) {
 | 
			
		||||
    return FromNodeBuffer(val, state, isolate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (val->IsObject()) {
 | 
			
		||||
    return FromV8Object(val.As<v8::Object>(), state, isolate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  LOG(ERROR) << "Unexpected v8 value type encountered.";
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<base::Value> V8ValueConverter::FromV8Array(
 | 
			
		||||
    v8::Local<v8::Array> val,
 | 
			
		||||
    FromV8ValueState* state,
 | 
			
		||||
    v8::Isolate* isolate) const {
 | 
			
		||||
  ScopedUniquenessGuard uniqueness_guard(state, val);
 | 
			
		||||
  if (!uniqueness_guard.is_valid())
 | 
			
		||||
    return std::make_unique<base::Value>();
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<v8::Context::Scope> scope;
 | 
			
		||||
  // If val was created in a different context than our current one, change to
 | 
			
		||||
  // that context, but change back after val is converted.
 | 
			
		||||
  if (!val->GetCreationContextChecked().IsEmpty() &&
 | 
			
		||||
      val->GetCreationContextChecked() != isolate->GetCurrentContext())
 | 
			
		||||
    scope =
 | 
			
		||||
        std::make_unique<v8::Context::Scope>(val->GetCreationContextChecked());
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<base::ListValue> result(new base::ListValue());
 | 
			
		||||
 | 
			
		||||
  // Only fields with integer keys are carried over to the ListValue.
 | 
			
		||||
  for (uint32_t i = 0; i < val->Length(); ++i) {
 | 
			
		||||
    v8::TryCatch try_catch(isolate);
 | 
			
		||||
    v8::Local<v8::Value> child_v8;
 | 
			
		||||
    v8::MaybeLocal<v8::Value> maybe_child =
 | 
			
		||||
        val->Get(isolate->GetCurrentContext(), i);
 | 
			
		||||
    if (try_catch.HasCaught() || !maybe_child.ToLocal(&child_v8)) {
 | 
			
		||||
      LOG(ERROR) << "Getter for index " << i << " threw an exception.";
 | 
			
		||||
      child_v8 = v8::Null(isolate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!val->HasRealIndexedProperty(isolate->GetCurrentContext(), i)
 | 
			
		||||
             .FromMaybe(false)) {
 | 
			
		||||
      result->Append(base::Value());
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<base::Value> child =
 | 
			
		||||
        FromV8ValueImpl(state, child_v8, isolate);
 | 
			
		||||
    if (child) {
 | 
			
		||||
      result->Append(base::Value::FromUniquePtrValue(std::move(child)));
 | 
			
		||||
    } else {
 | 
			
		||||
      // JSON.stringify puts null in places where values don't serialize, for
 | 
			
		||||
      // example undefined and functions. Emulate that behavior.
 | 
			
		||||
      result->Append(base::Value());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return std::move(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<base::Value> V8ValueConverter::FromNodeBuffer(
 | 
			
		||||
    v8::Local<v8::Value> value,
 | 
			
		||||
    FromV8ValueState* state,
 | 
			
		||||
    v8::Isolate* isolate) const {
 | 
			
		||||
  std::vector<char> buffer(
 | 
			
		||||
      node::Buffer::Data(value),
 | 
			
		||||
      node::Buffer::Data(value) + node::Buffer::Length(value));
 | 
			
		||||
  return std::make_unique<base::Value>(std::move(buffer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<base::Value> V8ValueConverter::FromV8Object(
 | 
			
		||||
    v8::Local<v8::Object> val,
 | 
			
		||||
    FromV8ValueState* state,
 | 
			
		||||
    v8::Isolate* isolate) const {
 | 
			
		||||
  ScopedUniquenessGuard uniqueness_guard(state, val);
 | 
			
		||||
  if (!uniqueness_guard.is_valid())
 | 
			
		||||
    return std::make_unique<base::Value>();
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<v8::Context::Scope> scope;
 | 
			
		||||
  // If val was created in a different context than our current one, change to
 | 
			
		||||
  // that context, but change back after val is converted.
 | 
			
		||||
  if (!val->GetCreationContextChecked().IsEmpty() &&
 | 
			
		||||
      val->GetCreationContextChecked() != isolate->GetCurrentContext())
 | 
			
		||||
    scope =
 | 
			
		||||
        std::make_unique<v8::Context::Scope>(val->GetCreationContextChecked());
 | 
			
		||||
 | 
			
		||||
  auto result = std::make_unique<base::DictionaryValue>();
 | 
			
		||||
  v8::Local<v8::Array> property_names;
 | 
			
		||||
  if (!val->GetOwnPropertyNames(isolate->GetCurrentContext())
 | 
			
		||||
           .ToLocal(&property_names)) {
 | 
			
		||||
    return std::move(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (uint32_t i = 0; i < property_names->Length(); ++i) {
 | 
			
		||||
    v8::Local<v8::Value> key =
 | 
			
		||||
        property_names->Get(isolate->GetCurrentContext(), i).ToLocalChecked();
 | 
			
		||||
 | 
			
		||||
    // Extend this test to cover more types as necessary and if sensible.
 | 
			
		||||
    if (!key->IsString() && !key->IsNumber()) {
 | 
			
		||||
      NOTREACHED() << "Key \"" << *v8::String::Utf8Value(isolate, key)
 | 
			
		||||
                   << "\" "
 | 
			
		||||
                      "is neither a string nor a number";
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v8::String::Utf8Value name_utf8(isolate, key);
 | 
			
		||||
 | 
			
		||||
    v8::TryCatch try_catch(isolate);
 | 
			
		||||
    v8::Local<v8::Value> child_v8;
 | 
			
		||||
    v8::MaybeLocal<v8::Value> maybe_child =
 | 
			
		||||
        val->Get(isolate->GetCurrentContext(), key);
 | 
			
		||||
    if (try_catch.HasCaught() || !maybe_child.ToLocal(&child_v8)) {
 | 
			
		||||
      LOG(ERROR) << "Getter for property " << *name_utf8
 | 
			
		||||
                 << " threw an exception.";
 | 
			
		||||
      child_v8 = v8::Null(isolate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<base::Value> child =
 | 
			
		||||
        FromV8ValueImpl(state, child_v8, isolate);
 | 
			
		||||
    if (!child)
 | 
			
		||||
      // JSON.stringify skips properties whose values don't serialize, for
 | 
			
		||||
      // example undefined and functions. Emulate that behavior.
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    // Strip null if asked (and since undefined is turned into null, undefined
 | 
			
		||||
    // too). The use case for supporting this is JSON-schema support,
 | 
			
		||||
    // specifically for extensions, where "optional" JSON properties may be
 | 
			
		||||
    // represented as null, yet due to buggy legacy code elsewhere isn't
 | 
			
		||||
    // treated as such (potentially causing crashes). For example, the
 | 
			
		||||
    // "tabs.create" function takes an object as its first argument with an
 | 
			
		||||
    // optional "windowId" property.
 | 
			
		||||
    //
 | 
			
		||||
    // Given just
 | 
			
		||||
    //
 | 
			
		||||
    //   tabs.create({})
 | 
			
		||||
    //
 | 
			
		||||
    // this will work as expected on code that only checks for the existence of
 | 
			
		||||
    // a "windowId" property (such as that legacy code). However given
 | 
			
		||||
    //
 | 
			
		||||
    //   tabs.create({windowId: null})
 | 
			
		||||
    //
 | 
			
		||||
    // there *is* a "windowId" property, but since it should be an int, code
 | 
			
		||||
    // on the browser which doesn't additionally check for null will fail.
 | 
			
		||||
    // We can avoid all bugs related to this by stripping null.
 | 
			
		||||
    if (strip_null_from_objects_ && child->is_none())
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
 | 
			
		||||
                                    std::move(child));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return std::move(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace electron
 | 
			
		||||
| 
						 | 
				
			
			@ -1,78 +0,0 @@
 | 
			
		|||
// Copyright (c) 2013 GitHub, Inc.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef ELECTRON_SHELL_COMMON_V8_VALUE_CONVERTER_H_
 | 
			
		||||
#define ELECTRON_SHELL_COMMON_V8_VALUE_CONVERTER_H_
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "base/compiler_specific.h"
 | 
			
		||||
#include "v8/include/v8.h"
 | 
			
		||||
 | 
			
		||||
namespace base {
 | 
			
		||||
class DictionaryValue;
 | 
			
		||||
class ListValue;
 | 
			
		||||
class Value;
 | 
			
		||||
}  // namespace base
 | 
			
		||||
 | 
			
		||||
namespace electron {
 | 
			
		||||
 | 
			
		||||
class V8ValueConverter {
 | 
			
		||||
 public:
 | 
			
		||||
  V8ValueConverter();
 | 
			
		||||
 | 
			
		||||
  // disable copy
 | 
			
		||||
  V8ValueConverter(const V8ValueConverter&) = delete;
 | 
			
		||||
  V8ValueConverter& operator=(const V8ValueConverter&) = delete;
 | 
			
		||||
 | 
			
		||||
  void SetRegExpAllowed(bool val);
 | 
			
		||||
  void SetFunctionAllowed(bool val);
 | 
			
		||||
  void SetStripNullFromObjects(bool val);
 | 
			
		||||
  v8::Local<v8::Value> ToV8Value(const base::Value* value,
 | 
			
		||||
                                 v8::Local<v8::Context> context) const;
 | 
			
		||||
  std::unique_ptr<base::Value> FromV8Value(
 | 
			
		||||
      v8::Local<v8::Value> value,
 | 
			
		||||
      v8::Local<v8::Context> context) const;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  class FromV8ValueState;
 | 
			
		||||
  class ScopedUniquenessGuard;
 | 
			
		||||
 | 
			
		||||
  v8::Local<v8::Value> ToV8ValueImpl(v8::Isolate* isolate,
 | 
			
		||||
                                     const base::Value* value) const;
 | 
			
		||||
  v8::Local<v8::Value> ToV8Array(v8::Isolate* isolate,
 | 
			
		||||
                                 const base::ListValue* list) const;
 | 
			
		||||
  v8::Local<v8::Value> ToV8Object(
 | 
			
		||||
      v8::Isolate* isolate,
 | 
			
		||||
      const base::DictionaryValue* dictionary) const;
 | 
			
		||||
  v8::Local<v8::Value> ToArrayBuffer(v8::Isolate* isolate,
 | 
			
		||||
                                     const base::Value* value) const;
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<base::Value> FromV8ValueImpl(FromV8ValueState* state,
 | 
			
		||||
                                               v8::Local<v8::Value> value,
 | 
			
		||||
                                               v8::Isolate* isolate) const;
 | 
			
		||||
  std::unique_ptr<base::Value> FromV8Array(v8::Local<v8::Array> array,
 | 
			
		||||
                                           FromV8ValueState* state,
 | 
			
		||||
                                           v8::Isolate* isolate) const;
 | 
			
		||||
  std::unique_ptr<base::Value> FromNodeBuffer(v8::Local<v8::Value> value,
 | 
			
		||||
                                              FromV8ValueState* state,
 | 
			
		||||
                                              v8::Isolate* isolate) const;
 | 
			
		||||
  std::unique_ptr<base::Value> FromV8Object(v8::Local<v8::Object> object,
 | 
			
		||||
                                            FromV8ValueState* state,
 | 
			
		||||
                                            v8::Isolate* isolate) const;
 | 
			
		||||
 | 
			
		||||
  // If true, we will convert RegExp JavaScript objects to string.
 | 
			
		||||
  bool reg_exp_allowed_ = false;
 | 
			
		||||
 | 
			
		||||
  // If true, we will convert Function JavaScript objects to dictionaries.
 | 
			
		||||
  bool function_allowed_ = false;
 | 
			
		||||
 | 
			
		||||
  // If true, undefined and null values are ignored when converting v8 objects
 | 
			
		||||
  // into Values.
 | 
			
		||||
  bool strip_null_from_objects_ = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace electron
 | 
			
		||||
 | 
			
		||||
#endif  // ELECTRON_SHELL_COMMON_V8_VALUE_CONVERTER_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,6 @@ describe('systemPreferences module', () => {
 | 
			
		|||
      const badDefaults = [
 | 
			
		||||
        1,
 | 
			
		||||
        null,
 | 
			
		||||
        new Date(),
 | 
			
		||||
        { one: null }
 | 
			
		||||
      ];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue