• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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