├── .gitignore ├── .pr-preview.json ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── deploy.sh ├── deploy_key.enc ├── explainer.md ├── index.bs └── w3c.json /.gitignore: -------------------------------------------------------------------------------- 1 | .deploy_key 2 | index.html 3 | out 4 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | script: bash ./deploy.sh 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | env: 10 | global: 11 | - ENCRYPTION_LABEL: 9c8a9644b4ae 12 | - COMMIT_AUTHOR_EMAIL: travis-ci@w3.org 13 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Encrypted Media: HDCP Policy Check 2 | 3 | Contributions to this repository are intended to become part of 4 | Recommendation-track documents governed by the [W3C Patent 5 | Policy](http://www.w3.org/Consortium/Patent-Policy-20040205/) and [Document 6 | License](http://www.w3.org/Consortium/Legal/copyright-documents). To contribute, 7 | you must either participate in the relevant W3C Working Group or make a 8 | non-member patent licensing commitment. 9 | 10 | If you are not the sole contributor to a contribution (pull request), please 11 | identify all contributors in the pull request's body or in subsequent comments. 12 | 13 | To add a contributor (other than yourself, that's automatic), mark them one per 14 | line as follows: 15 | 16 | ``` 17 | +@github_username 18 | ``` 19 | 20 | If you added a contributor by mistake, you can remove them in a comment with: 21 | 22 | ``` 23 | -@github_username 24 | ``` 25 | 26 | If you are making a pull request on behalf of someone else but you had no part 27 | in designing the feature, you can remove yourself with the above syntax. 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C Document 2 | License](http://www.w3.org/Consortium/Legal/copyright-documents). 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LOCAL_BIKESHED := $(shell command -v bikeshed 2> /dev/null) 2 | 3 | index.html: index.bs 4 | ifndef LOCAL_BIKESHED 5 | curl https://api.csswg.org/bikeshed/ -f -F file=@$< -o $@ 6 | else 7 | bikeshed spec 8 | endif 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hdcp-detection 2 | Incubation for HDCP detection feature in EME 3 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e # Exit with nonzero exit code if anything fails 3 | 4 | SOURCE_BRANCH="master" 5 | TARGET_BRANCH="gh-pages" 6 | 7 | # Pull requests and commits to other branches shouldn't try to deploy, just build to verify 8 | if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then 9 | echo "Skipping deploy; just doing a build." 10 | make 11 | exit 0 12 | fi 13 | 14 | # Save some useful information 15 | REPO=`git config remote.origin.url` 16 | SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:} 17 | SHA=`git rev-parse --verify HEAD` 18 | 19 | # Clone the existing gh-pages for this repo into out/ 20 | # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply) 21 | git clone $REPO out 22 | cd out 23 | git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH 24 | cd .. 25 | 26 | # Clean out existing contents 27 | rm -rf out/* || exit 0 28 | 29 | # Build the html output 30 | make && mv index.html out/index.html 31 | 32 | # Now let's go have some fun with the cloned repo 33 | cd out 34 | git config user.name "Travis CI" 35 | git config user.email "$COMMIT_AUTHOR_EMAIL" 36 | 37 | # If there are no changes to the compiled out (e.g. this is a README update) then just bail. 38 | if [[ -z $(git status -s) ]]; then 39 | echo "No changes to the output on this push; exiting." 40 | exit 0 41 | fi 42 | 43 | # Commit the "changes", i.e. the new version. 44 | # The delta will show diffs between new and old versions. 45 | git add . 46 | git commit -m "Deploy to GitHub Pages: ${SHA}" 47 | 48 | # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc 49 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" 50 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" 51 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} 52 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} 53 | openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out deploy_key -d 54 | chmod 600 deploy_key 55 | eval `ssh-agent -s` 56 | ssh-add deploy_key 57 | 58 | # Now that we're all set up, we can push. 59 | git push $SSH_REPO $TARGET_BRANCH 60 | -------------------------------------------------------------------------------- /deploy_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/hdcp-detection/c3a7b9bb6975bff1fe790f5381ddbe084a78c03e/deploy_key.enc -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # EME Extension: HDCP Policy Check 2 | 3 | ## Motivation 4 | 5 | A content license can contain a policy that the CDM must enforce. The ability 6 | of a platform to enforce these policies is a key factor in deciding whether to 7 | begin streaming media and at what quality (resolution and framerate). 8 | 9 | HDCP is a common policy requirement for streaming high resolutions of protected 10 | content. Currently, applications can only know if this requirements is met 11 | through key statuses, which are only reported after providing a license. To 12 | provide a license, applications must: generate a license request, post that 13 | request to a license server, wait for the response, provide the response to the 14 | CDM, wait for key status events, and check key statuses. 15 | 16 | Application developers would like to know before fetching content if HDCP (and 17 | what version) can be enforced. This would allow the application to start 18 | pre-fetching high resolution content rather than starting at a low resolution or 19 | waiting for the license exchange. 20 | 21 | HDCP may be one of many requirements for a content license. The proposed 22 | dictionary may later be extended to include other requirements as requested by 23 | application developers. Feature detection can be done by developers by setting 24 | throwing getters. 25 | 26 | 27 | ## Overview 28 | 29 | The new API will allow application developers to query the status of a 30 | hypothetical key associated with an HDCP policy, without the need to create a 31 | MediaKeySession or fetch a real license. It does not require the MediaKeys to be 32 | attached to any HTMLMediaElement, either. 33 | 34 | If HDCP is available at the specified version, the promise should return 35 | a MediaKeyStatus of "usable". Otherwise, the promise should return 36 | a MediaKeyStatus of "output-restricted". The determination of HDCP status 37 | should be done in the same way that the CDM would enforce such a restriction 38 | during playback. In this way, application developers can get a reasonable hint 39 | to allow them to optimize what content they fetch to start playback. 40 | 41 | A MediaKeyStatus value of "status-pending" must never be returned. Implementers 42 | must give decisive actionable return values for developers to make decisions 43 | about what content to fetch. 44 | 45 | ``` 46 | dictionary MediaKeysPolicy { 47 | DOMString minHdcpVersion = ""; 48 | }; 49 | 50 | partial interface MediaKeys { 51 | Promise getStatusForPolicy(MediaKeysPolicy policy); 52 | } 53 | ``` 54 | 55 | The HDCP versions will be kept in a registry. The initial list will contain: 56 | ``` 57 | - 1.0 58 | - 1.1 59 | - 1.2 60 | - 1.3 61 | - 1.4 62 | - 2.0 63 | - 2.1 64 | - 2.2 65 | - 2.3 66 | 67 | ``` 68 | 69 | 70 | ## Examples 71 | 72 | ```js 73 | video.mediaKeys.getStatusForPolicy({ 74 | minHdcpVersion: '1.0' 75 | }).then(status => { 76 | if (status === 'usable') { 77 | // Pre-fetch HD content. 78 | } else { // such as 'output-restricted' or 'output-downscaled' 79 | // Pre-fetch SD content. 80 | } 81 | }); 82 | ``` 83 | 84 | 85 | ## Privacy Considerations 86 | 87 | This would allow an application to discover HDCP availability. HDCP is widely 88 | available on most modern operating systems and display types. It is not expected 89 | to add much entropy for fingerprinting. 90 | 91 | As access to this API is gated by the async `requestMediaKeySystemAccess()` which 92 | may require user consent, the HDCP privacy concerns are the same as the 93 | [EME ones](https://w3c.github.io/encrypted-media/#privacy). 94 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
  2 | Title: Encrypted Media: HDCP Policy Check
  3 | Repository: wicg/hdcp-detection
  4 | Status: CG-DRAFT
  5 | ED: https://wicg.github.io/hdcp-detection/
  6 | Shortname: hdcp-detection
  7 | Level: 1
  8 | Group: wicg
  9 | Editor: Mounir Lamouri, w3cid 45389, Google Inc. https://google.com/
 10 | Editor: Joey Parrish, w3cid 105371, Google Inc. https://google.com/
 11 | 
 12 | Abstract: This specification intends to provide an extension to the W3C
 13 | Abstract: Encrypted Media Extension specification. The API will allow authors
 14 | Abstract: to query the policies that the CDM is able to enforce before
 15 | Abstract: requesting a key.
 16 | 
 17 | !Participate: Git Repository.
 18 | !Participate: File an issue.
 19 | !Version History: https://github.com/wicg/hdcp-detection/commits
 20 | 
21 | 22 |
 23 | spec: webidl; urlPrefix: https://heycam.github.io/webidl/
 24 |     type: dfn
 25 |         text: member; url: #dfn-dictionary-member
 26 |         text: present; url: #dfn-present
 27 | 
 28 | spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/
 29 |     type: interface
 30 |         text: TypeError; url: #sec-native-error-types-used-in-this-standard-typeerror
 31 | 
 32 | spec: encrypted-media; for: EME; urlPrefix: https://www.w3.org/TR/encrypted-media/
 33 |     type: interface
 34 |         text: MediaKeys; url: #mediakeys-interface
 35 |         text: MediaKeyStatus; url: #dom-mediakeystatus
 36 |         text: output-restricted; url: #idl-def-MediaKeyStatus.output-restricted
 37 |         text: usable; url: #idl-def-MediaKeyStatus.usable
 38 |         text: requestMediaKeySystemAccess(); url: #navigator-extension:-requestmediakeysystemaccess()
 39 | 
40 | 41 | 45 | 46 |
47 |

48 | MediaKeys Policies 49 |

50 | 51 |
52 |

53 | MediaKeysPolicy Dictionary 54 |

55 | 56 |
 57 |       dictionary MediaKeysPolicy {
 58 |         HDCPVersion minHdcpVersion;
 59 |       };
 60 |     
61 | 62 |

63 | The {{MediaKeysPolicy}} dictionary is an object consisting of only 64 | optional properties. Each property represents a policy requirement. 65 |

66 | 67 |

68 | A policy requirement is said to be fulfilled if the 69 | system matches the requirements. The exact requirements to match each 70 | policy requirement are defined below. 71 |

72 |
73 | 74 |
75 |

76 | HDCP Policy 77 |

78 | 79 |

80 | Using an enum as a shorthand. The final result will be similar in 81 | behaviour (TypeError) but may be based on a registry so the list can be 82 | updated without updating this document. 83 |

84 | 85 |
 86 |       enum HDCPVersion {
 87 |         "1.0",
 88 |         "1.1",
 89 |         "1.2",
 90 |         "1.3",
 91 |         "1.4",
 92 |         "2.0",
 93 |         "2.1",
 94 |         "2.2",
 95 |         "2.3",
 96 |       };
 97 |     
98 | 99 |

100 | The HDCP Policy is represented by the {{minHdcpVersion}}. When set, the 101 | policy requirement will be fulfilled if the system supports 102 | {{minHdcpVersion}} on the current display. 103 |

104 | 105 |
106 |
107 | 108 |
109 |

MediaKeys extension

110 | 111 |
112 |     [SecureContext, Exposed=Window]
113 |     partial interface MediaKeys {
114 |       [NewObject] Promise<MediaKeyStatus> getStatusForPolicy(optional MediaKeysPolicy policy);
115 |     };
116 |   
117 | 118 |

119 | The {{getStatusForPolicy}} method MUST run the following steps: 120 |

    121 |
  1. 122 | If policy has no present member, return a 123 | Promise rejected with a newly created {{TypeError}}. 124 |
  2. 125 |
  3. 126 | Let p be a new Promise. 127 |
  4. 128 |
  5. 129 | For each member of policy, run the following steps: 130 |
      131 |
    1. 132 | If the policy requirement associated with the member 133 | is not fulfilled, resolve p with 134 | {{output-restricted}} and abort these steps. 135 |
    2. 136 |
    137 |
  6. 138 |
  7. 139 | Resolve p with {{usable}}. 140 |
  8. 141 |
142 |

143 |
144 | 145 |
146 |

147 | Security and Privacy Considerations 148 |

149 | 150 |
151 |

152 | This specification does not introduce any security-sensitive information 153 | or APIs but it provides an easier access to some information. 154 |

155 | 156 |
157 |

158 | Fingerprinting 159 |

160 | 161 |

162 | The API offers access to some information that can already be accessed 163 | by the page through the CDM. This information does not increase the 164 | fingerprint surface but can make it simpler for a website to fingerprint 165 | its users as the information is easier to access and no longer requires 166 | getting a content license from a license server. 167 |

168 | 169 |

170 | The information added by this API, regardless of whether or not it is 171 | accessible in other ways, does not increase the entropy for 172 | fingerprinting much. HDCP is widely available on most operating systems 173 | and displays. 174 |

175 |
176 | 177 |
178 | 181 | 182 |

183 | The fingerprinting concerns are mitigated by the fact that the API is 184 | only accessible after {{requestMediaKeySystemAccess()}} was 185 | called, which may require user consent. UAs that would require user 186 | consent in order to access the CDM will therefore require user consent 187 | to access this API. 188 |

189 |
190 |
191 |
192 | 193 |
194 |

Examples

195 | 196 |
197 |
198 |       const status = await video.mediaKeys.getStatusForPolicy({
199 |         minHdcpVersion: '1.0'
200 |       });
201 | 
202 |       if (status === 'usable') {
203 |         // Pre-fetch HD content.
204 |       } else {  // such as 'output-restricted' or 'output-downscaled'
205 |         // Pre-fetch SD content.
206 |       }
207 |     
208 |
209 |
210 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["marcoscaceres"] 4 | , "repo-type": "cg-report" 5 | } 6 | --------------------------------------------------------------------------------