blob: 75632bd967db02b19f7d11890dc722803bd072d1 [file] [log] [blame]
// Copyright (c) 2016 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/drm_test.h"
#include <algorithm>
#include <string>
#include "include/cef_parser.h"
#include "include/cef_web_plugin.h"
#include "tests/cefclient/browser/test_runner.h"
namespace client {
namespace drm_test {
namespace {
// Application-specific error codes.
const int kMessageFormatError = 1;
const int kCdmLoadError = 2;
const char kTestUrlPath[] = "/drm";
const char kWidevineCdmPathKey[] = "widevine_cdm_path";
// Callback executed once CDM registration is complete.
class CdmCallback : public CefRegisterCdmCallback {
public:
CdmCallback(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback)
: callback_(callback) {}
void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
const CefString& error_message) OVERRIDE {
if (result == CEF_CDM_REGISTRATION_ERROR_NONE)
callback_->Success("");
else
callback_->Failure(kCdmLoadError, error_message);
callback_ = nullptr;
}
private:
CefRefPtr<CefMessageRouterBrowserSide::Callback> callback_;
IMPLEMENT_REFCOUNTING(CdmCallback);
DISALLOW_COPY_AND_ASSIGN(CdmCallback);
};
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {}
// Called due to cefQuery execution in drm.html.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (!test_runner::IsTestURL(url, kTestUrlPath))
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 "widevine_cdm_path" key.
if (!VerifyKey(request_dict, kWidevineCdmPathKey, VTYPE_STRING, callback))
return true;
const std::string& widevine_cdm_path =
request_dict->GetString(kWidevineCdmPathKey);
if (widevine_cdm_path.empty()) {
callback->Failure(kMessageFormatError, "Empty widevine CDM path");
return true;
}
// Register the Widvine CDM.
CefRegisterWidevineCdm(widevine_cdm_path, new CdmCallback(callback));
return true;
}
private:
// 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 nullptr;
}
// 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;
}
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace drm_test
} // namespace client