1 // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "tests/cefclient/browser/drm_test.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "include/cef_parser.h"
11 #include "include/cef_web_plugin.h"
12 #include "tests/cefclient/browser/test_runner.h"
13
14 namespace client {
15 namespace drm_test {
16
17 namespace {
18
19 // Application-specific error codes.
20 const int kMessageFormatError = 1;
21 const int kCdmLoadError = 2;
22
23 const char kTestUrlPath[] = "/drm";
24 const char kWidevineCdmPathKey[] = "widevine_cdm_path";
25
26 // Callback executed once CDM registration is complete.
27 class CdmCallback : public CefRegisterCdmCallback {
28 public:
CdmCallback(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback)29 CdmCallback(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback)
30 : callback_(callback) {}
31
OnCdmRegistrationComplete(cef_cdm_registration_error_t result,const CefString & error_message)32 void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
33 const CefString& error_message) OVERRIDE {
34 if (result == CEF_CDM_REGISTRATION_ERROR_NONE)
35 callback_->Success("");
36 else
37 callback_->Failure(kCdmLoadError, error_message);
38 callback_ = nullptr;
39 }
40
41 private:
42 CefRefPtr<CefMessageRouterBrowserSide::Callback> callback_;
43
44 IMPLEMENT_REFCOUNTING(CdmCallback);
45 DISALLOW_COPY_AND_ASSIGN(CdmCallback);
46 };
47
48 // Handle messages in the browser process.
49 class Handler : public CefMessageRouterBrowserSide::Handler {
50 public:
Handler()51 Handler() {}
52
53 // Called due to cefQuery execution in drm.html.
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)54 virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
55 CefRefPtr<CefFrame> frame,
56 int64 query_id,
57 const CefString& request,
58 bool persistent,
59 CefRefPtr<Callback> callback) OVERRIDE {
60 // Only handle messages from the test URL.
61 const std::string& url = frame->GetURL();
62 if (!test_runner::IsTestURL(url, kTestUrlPath))
63 return false;
64
65 // Parse |request| as a JSON dictionary.
66 CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
67 if (!request_dict) {
68 callback->Failure(kMessageFormatError, "Incorrect message format");
69 return true;
70 }
71
72 // Verify the "widevine_cdm_path" key.
73 if (!VerifyKey(request_dict, kWidevineCdmPathKey, VTYPE_STRING, callback))
74 return true;
75
76 const std::string& widevine_cdm_path =
77 request_dict->GetString(kWidevineCdmPathKey);
78 if (widevine_cdm_path.empty()) {
79 callback->Failure(kMessageFormatError, "Empty widevine CDM path");
80 return true;
81 }
82
83 // Register the Widvine CDM.
84 CefRegisterWidevineCdm(widevine_cdm_path, new CdmCallback(callback));
85 return true;
86 }
87
88 private:
89 // Convert a JSON string to a dictionary value.
ParseJSON(const CefString & string)90 static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
91 CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
92 if (value.get() && value->GetType() == VTYPE_DICTIONARY)
93 return value->GetDictionary();
94 return nullptr;
95 }
96
97 // Verify that |key| exists in |dictionary| and has type |value_type|. Fails
98 // |callback| and returns false on failure.
VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,const char * key,cef_value_type_t value_type,CefRefPtr<Callback> callback)99 static bool VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,
100 const char* key,
101 cef_value_type_t value_type,
102 CefRefPtr<Callback> callback) {
103 if (!dictionary->HasKey(key) || dictionary->GetType(key) != value_type) {
104 callback->Failure(
105 kMessageFormatError,
106 "Missing or incorrectly formatted message key: " + std::string(key));
107 return false;
108 }
109 return true;
110 }
111 };
112
113 } // namespace
114
CreateMessageHandlers(test_runner::MessageHandlerSet & handlers)115 void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
116 handlers.insert(new Handler());
117 }
118
119 } // namespace drm_test
120 } // namespace client
121