]> git.sesse.net Git - casparcg/blobdiff - dependencies64/cef/linux/tests/cefclient/browser/preferences_test.cc
Upgrade CEF to 3.3029.1611.g44e39a8 / Chromium 58.0.3029.81.
[casparcg] / dependencies64 / cef / linux / tests / cefclient / browser / preferences_test.cc
diff --git a/dependencies64/cef/linux/tests/cefclient/browser/preferences_test.cc b/dependencies64/cef/linux/tests/cefclient/browser/preferences_test.cc
new file mode 100644 (file)
index 0000000..3a1a205
--- /dev/null
@@ -0,0 +1,337 @@
+// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#include "tests/cefclient/browser/preferences_test.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "include/base/cef_logging.h"
+#include "include/cef_command_line.h"
+#include "include/cef_parser.h"
+
+namespace client {
+namespace preferences_test {
+
+namespace {
+
+const char kTestUrl[] = "http://tests/preferences";
+
+// Application-specific error codes.
+const int kMessageFormatError = 1;
+const int kPreferenceApplicationError = 1;
+
+// Common to all messages.
+const char kNameKey[] = "name";
+const char kNameValueGet[] = "preferences_get";
+const char kNameValueSet[] = "preferences_set";
+const char kNameValueState[] = "preferences_state";
+
+// Used with "preferences_get" messages.
+const char kIncludeDefaultsKey[] = "include_defaults";
+
+// Used with "preferences_set" messages.
+const char kPreferencesKey[] = "preferences";
+
+// Handle messages in the browser process. Only accessed on the UI thread.
+class Handler : public CefMessageRouterBrowserSide::Handler {
+ public:
+  typedef std::vector<std::string> NameVector;
+
+  Handler() {
+    CEF_REQUIRE_UI_THREAD();
+  }
+
+  // Called due to cefQuery execution in preferences.html.
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64 query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) OVERRIDE {
+    CEF_REQUIRE_UI_THREAD();
+
+    // Only handle messages from the test URL.
+    std::string url = frame->GetURL();
+    if (url.find(kTestUrl) != 0)
+      return false;
+
+    // Parse |request| as a JSON dictionary.
+    CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
+    if (!request_dict) {
+      callback->Failure(kMessageFormatError, "Incorrect message format");
+      return true;
+    }
+
+    // Verify the "name" key.
+    if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback))
+      return true;
+
+    const std::string& message_name = request_dict->GetString(kNameKey);
+    if (message_name == kNameValueGet) {
+      // JavaScript is requesting a JSON representation of the preferences tree.
+
+      // Verify the "include_defaults" key.
+      if (!VerifyKey(request_dict, kIncludeDefaultsKey, VTYPE_BOOL, callback))
+        return true;
+
+      const bool include_defaults = request_dict->GetBool(kIncludeDefaultsKey);
+
+      OnPreferencesGet(browser, include_defaults, callback);
+
+      return true;
+    } else if (message_name == kNameValueSet) {
+      // JavaScript is requesting that preferences be updated to match the
+      // specified JSON representation.
+
+      // Verify the "preferences" key.
+      if (!VerifyKey(request_dict, kPreferencesKey, VTYPE_DICTIONARY, callback))
+        return true;
+
+      CefRefPtr<CefDictionaryValue> preferences =
+          request_dict->GetDictionary(kPreferencesKey);
+
+      OnPreferencesSet(browser, preferences, callback);
+
+      return true;
+    } else if (message_name == kNameValueState) {
+      // JavaScript is requesting global state information.
+
+      OnPreferencesState(browser, callback);
+
+      return true;
+    }
+
+    return false;
+  }
+
+ private:
+  // Execute |callback| with the preferences dictionary as a JSON string.
+  static void OnPreferencesGet(CefRefPtr<CefBrowser> browser,
+                               bool include_defaults,
+                               CefRefPtr<Callback> callback) {
+    CefRefPtr<CefRequestContext> context =
+        browser->GetHost()->GetRequestContext();
+
+    // Retrieve all preference values.
+    CefRefPtr<CefDictionaryValue> prefs =
+        context->GetAllPreferences(include_defaults);
+
+    // Serialize the preferences to JSON and return to the JavaScript caller.
+    callback->Success(GetJSON(prefs));
+  }
+
+  // Set preferences based on the contents of |preferences|. Execute |callback|
+  // with a descriptive result message.
+  static void OnPreferencesSet(CefRefPtr<CefBrowser> browser,
+                               CefRefPtr<CefDictionaryValue> preferences,
+                               CefRefPtr<Callback> callback) {
+    CefRefPtr<CefRequestContext> context =
+        browser->GetHost()->GetRequestContext();
+
+    CefRefPtr<CefValue> value = CefValue::Create();
+    value->SetDictionary(preferences);
+
+    std::string error;
+    NameVector changed_names;
+
+    // Apply preferences. This may result in errors.
+    const bool success = ApplyPrefs(context, std::string(), value, error,
+                                    changed_names);
+
+    // Create a message that accurately represents the result.
+    std::string message;
+    if (!changed_names.empty()) {
+      std::stringstream ss;
+      ss << "Successfully changed " << changed_names.size() <<
+            " preferences; ";
+      for (size_t i = 0; i < changed_names.size(); ++i) {
+        ss << changed_names[i];
+        if (i < changed_names.size() - 1)
+          ss << ", ";
+      }
+      message = ss.str();
+    }
+
+    if (!success) {
+      DCHECK(!error.empty());
+      if (!message.empty())
+        message += "\n";
+      message += error;
+    }
+
+    if (changed_names.empty()) {
+      if (!message.empty())
+        message += "\n";
+      message += "No preferences changed.";
+    }
+
+    // Return the message to the JavaScript caller.
+    if (success)
+      callback->Success(message);
+    else
+      callback->Failure(kPreferenceApplicationError, message);
+  }
+
+  // Execute |callback| with the global state dictionary as a JSON string.
+  static void OnPreferencesState(CefRefPtr<CefBrowser> browser,
+                                 CefRefPtr<Callback> callback) {
+    CefRefPtr<CefCommandLine> command_line =
+        CefCommandLine::GetGlobalCommandLine();
+
+    CefRefPtr<CefDictionaryValue> dict = CefDictionaryValue::Create();
+
+    // If spell checking is disabled via the command-line then it cannot be
+    // enabled via preferences.
+    dict->SetBool("spellcheck_disabled",
+        command_line->HasSwitch("disable-spell-checking"));
+
+    // If proxy settings are configured via the command-line then they cannot
+    // be modified via preferences.
+    dict->SetBool("proxy_configured",
+        command_line->HasSwitch("no-proxy-server") ||
+        command_line->HasSwitch("proxy-auto-detect") ||
+        command_line->HasSwitch("proxy-pac-url") ||
+        command_line->HasSwitch("proxy-server"));
+
+    // If allow running insecure content is enabled via the command-line then it
+    // cannot be enabled via preferences.
+    dict->SetBool("allow_running_insecure_content",
+        command_line->HasSwitch("allow-running-insecure-content"));
+
+    // Serialize the state to JSON and return to the JavaScript caller.
+    callback->Success(GetJSON(dict));
+  }
+
+  // Convert a JSON string to a dictionary value.
+  static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
+    CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
+    if (value.get() && value->GetType() == VTYPE_DICTIONARY)
+      return value->GetDictionary();
+    return NULL;
+  }
+
+  // Convert a dictionary value to a JSON string.
+  static CefString GetJSON(CefRefPtr<CefDictionaryValue> dictionary) {
+    CefRefPtr<CefValue> value = CefValue::Create();
+    value->SetDictionary(dictionary);
+    return CefWriteJSON(value, JSON_WRITER_DEFAULT);
+  }
+
+  // Verify that |key| exists in |dictionary| and has type |value_type|. Fails
+  // |callback| and returns false on failure.
+  static bool VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,
+                        const char* key,
+                        cef_value_type_t value_type,
+                        CefRefPtr<Callback> callback) {
+    if (!dictionary->HasKey(key) || dictionary->GetType(key) != value_type) {
+      callback->Failure(kMessageFormatError,
+                        "Missing or incorrectly formatted message key: " +
+                        std::string(key));
+      return false;
+    }
+    return true;
+  }
+
+  // Apply preferences. Returns true on success. Returns false and sets |error|
+  // to a descriptive error string on failure. |changed_names| is the list of
+  // preferences that were successfully changed.
+  static bool ApplyPrefs(CefRefPtr<CefRequestContext> context,
+                         const std::string& name,
+                         CefRefPtr<CefValue> value,
+                         std::string& error,
+                         NameVector& changed_names) {
+    if (!name.empty() && context->HasPreference(name)) {
+      // The preference exists. Set the value.
+      return SetPref(context, name, value, error, changed_names);
+    }
+
+    if (value->GetType() == VTYPE_DICTIONARY) {
+      // A dictionary type value that is not an existing preference. Try to set
+      // each of the elements individually.
+      CefRefPtr<CefDictionaryValue> dict = value->GetDictionary();
+
+      CefDictionaryValue::KeyList keys;
+      dict->GetKeys(keys);
+      for (size_t i = 0; i < keys.size(); ++i) {
+        const std::string& key = keys[i];
+        const std::string& current_name =
+            name.empty() ? key : name + "." + key;
+        if (!ApplyPrefs(context, current_name, dict->GetValue(key), error,
+                        changed_names)) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
+    error = "Trying to create an unregistered preference: " + name;
+    return false;
+  }
+
+  // Set a specific preference value. Returns true if the value is set
+  // successfully or has not changed. If the value has changed then |name| will
+  // be added to |changed_names|. Returns false and sets |error| to a
+  // descriptive error string on failure.
+  static bool SetPref(CefRefPtr<CefRequestContext> context,
+                      const std::string& name,
+                      CefRefPtr<CefValue> value,
+                      std::string& error,
+                      NameVector& changed_names) {
+    CefRefPtr<CefValue> existing_value = context->GetPreference(name);
+    DCHECK(existing_value);
+
+    if (value->GetType() == VTYPE_STRING &&
+        existing_value->GetType() != VTYPE_STRING) {
+      // Since |value| is coming from JSON all basic types will be represented
+      // as strings. Convert to the expected data type.
+      const std::string& string_val = value->GetString();
+      switch (existing_value->GetType()) {
+        case VTYPE_BOOL:
+          if (string_val == "true" || string_val == "1")
+            value->SetBool(true);
+          else if (string_val == "false" || string_val == "0")
+            value->SetBool(false);
+          break;
+        case VTYPE_INT:
+          value->SetInt(atoi(string_val.c_str()));
+          break;
+        case VTYPE_DOUBLE:
+          value->SetInt(atof(string_val.c_str()));
+          break;
+        default:
+          // Other types cannot be converted.
+          break;
+      }
+    }
+
+    // Nothing to do if the value hasn't changed.
+    if (existing_value->IsEqual(value))
+      return true;
+
+    // Attempt to set the preference.
+    CefString error_str;
+    if (!context->SetPreference(name, value, error_str)) {
+      error = error_str.ToString() + ": " + name;
+      return false;
+    }
+
+    // The preference was set successfully.
+    changed_names.push_back(name);
+    return true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(Handler);
+};
+
+}  // namespace
+
+void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
+  handlers.insert(new Handler());
+}
+
+}  // namespace preferences_test
+}  // namespace client