Skip to content

Commit d6bf0d8

Browse files
committed
Logger refactor
1 parent 39c45bf commit d6bf0d8

File tree

8 files changed

+129
-79
lines changed

8 files changed

+129
-79
lines changed

injected/integration-test/test-pages/duckplayer/config/native.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"errorContainer": "body",
1010
"signInRequiredError": "[href*=\"//support.google.com/youtube/answer/3037019\"]",
1111
"videoElement": "#player video",
12-
"videoElementContainer": "#player .html5-video-player"
12+
"videoElementContainer": "#player .html5-video-player",
13+
"youtubeError": ".ytp-error"
1314
},
1415
"domains": []
1516
}

injected/src/features/duck-player-native.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Environment } from './duckplayer-native/environment.js';
1212

1313
export class DuckPlayerNativeFeature extends ContentFeature {
1414
init(args) {
15-
console.log('[duckplayer-native] Loading', args);
15+
console.log('DUCK PLAYER NATIVE LOADING', args);
1616

1717
// TODO: Should we keep this?
1818
/**
@@ -25,8 +25,8 @@ export class DuckPlayerNativeFeature extends ContentFeature {
2525
*/
2626
// TODO: Why isn't this working?
2727
// const settings = this.getFeatureSetting('settings');
28-
const settings = args?.featureSettings?.duckPlayerNative;
29-
console.log('[duckplayer-native] Selectors', settings?.selectors);
28+
const settings = args?.featureSettings?.duckPlayerNative?.settings || args?.featureSettings?.duckPlayerNative;
29+
console.log('DUCK PLAYER NATIVE SELECTORS', settings?.selectors);
3030

3131
const locale = args?.locale || args?.language || 'en';
3232
const env = new Environment({

injected/src/features/duckplayer-native/custom-error/custom-error.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import css from './custom-error.css';
2+
import { Logger } from '../util';
23
import { createPolicy, html } from '../../../dom-utils.js';
34
import { customElementsDefine, customElementsGet } from '../../../captured-globals.js';
45

@@ -12,6 +13,8 @@ export class CustomError extends HTMLElement {
1213
static CUSTOM_TAG_NAME = 'ddg-video-error';
1314

1415
policy = createPolicy();
16+
/** @type {Logger} */
17+
logger;
1518
/** @type {boolean} */
1619
testMode = false;
1720
/** @type {YouTubeError} */
@@ -27,12 +30,6 @@ export class CustomError extends HTMLElement {
2730
}
2831
}
2932

30-
log(message, force = false) {
31-
if (this.testMode || force) {
32-
console.log(`[custom-error] ${message}`);
33-
}
34-
}
35-
3633
connectedCallback() {
3734
this.createMarkupAndStyles();
3835
}
@@ -50,9 +47,7 @@ export class CustomError extends HTMLElement {
5047
shadow.append(style, container);
5148
this.container = container;
5249

53-
if (this.testMode) {
54-
this.log(`Created ${CustomError.CUSTOM_TAG_NAME} with container ${container}`);
55-
}
50+
this.logger?.log('Created', CustomError.CUSTOM_TAG_NAME, 'with container', container);
5651
}
5752

5853
/**
@@ -88,7 +83,7 @@ export class CustomError extends HTMLElement {
8883
*/
8984
function getErrorStrings(environment, errorId) {
9085
// TODO: get from environment strings
91-
console.log(`Getting translations for ${errorId} from ${environment}`);
86+
console.log('TODO: Get translations for ', errorId, 'from', environment);
9287
return {
9388
title: 'YouTube won’t let Duck Player load this video',
9489
messages: [
@@ -106,9 +101,15 @@ function getErrorStrings(environment, errorId) {
106101
*/
107102
export function showError(targetElement, environment, errorId) {
108103
const { title, messages } = getErrorStrings(environment, errorId);
104+
const logger = new Logger({
105+
id: 'CUSTOM_ERROR',
106+
shouldLog: () => environment.isTestMode(),
107+
});
108+
109109
CustomError.register();
110110

111111
const customError = /** @type {CustomError} */ (document.createElement(CustomError.CUSTOM_TAG_NAME));
112+
customError.logger = logger;
112113
customError.testMode = environment.isTestMode();
113114
customError.title = title;
114115
customError.messages = messages;

injected/src/features/duckplayer-native/duckplayer-native.js

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import { ErrorDetection } from './error-detection.js';
66
import { appendThumbnailOverlay } from './overlays/thumbnail-overlay.js';
77
import { stopVideoFromPlaying } from './pause-video.js';
88
import { showError } from './custom-error/custom-error.js';
9+
import { Logger } from './util.js';
910

1011
/**
1112
* @typedef {object} DuckPlayerNativeSettings
1213
* @property {import("@duckduckgo/privacy-configuration/schema/features/duckplayer-native.js").DuckPlayerNativeSettings['selectors']} selectors
1314
*/
1415

1516
export class DuckPlayerNative {
17+
/** @type {Logger} */
18+
logger;
1619
/** @type {DuckPlayerNativeSettings} */
1720
settings;
1821
/** @type {import('./environment.js').Environment} */
@@ -32,16 +35,18 @@ export class DuckPlayerNative {
3235
throw new Error('Missing arguments');
3336
}
3437

38+
this.setupLogger();
39+
3540
this.settings = settings;
3641
this.environment = environment;
3742
this.messages = messages;
3843
}
3944

40-
// TODO: Is there a class or module that does this already?
41-
log(message, force = false) {
42-
if (this.environment.isTestMode() || force) {
43-
console.log(`[duckplayer-native] ${message}`);
44-
}
45+
setupLogger() {
46+
this.logger = new Logger({
47+
id: 'DUCK_PLAYER_NATIVE',
48+
shouldLog: () => this.environment.isTestMode(),
49+
});
4550
}
4651

4752
async init() {
@@ -56,7 +61,7 @@ export class DuckPlayerNative {
5661
return;
5762
}
5863

59-
console.log('INITIAL SETUP', initialSetup);
64+
this.logger.log('INITIAL SETUP', initialSetup);
6065

6166
this.setupMessaging();
6267
this.setupErrorDetection();
@@ -79,7 +84,7 @@ export class DuckPlayerNative {
7984
}
8085

8186
setupErrorDetection() {
82-
this.log('Setting up error detection');
87+
this.logger.log('Setting up error detection');
8388
const errorContainer = this.settings.selectors?.errorContainer;
8489
const signInRequiredError = this.settings.selectors?.signInRequiredError;
8590
if (!errorContainer || !signInRequiredError) {
@@ -89,7 +94,7 @@ export class DuckPlayerNative {
8994

9095
/** @type {(errorId: import('./error-detection.js').YouTubeError) => void} */
9196
const errorHandler = (errorId) => {
92-
this.log(`Received error ${errorId}`);
97+
this.logger.log('Received error', errorId);
9398

9499
// Notify the browser of the error
95100
this.messages.onYoutubeError(errorId);
@@ -102,7 +107,7 @@ export class DuckPlayerNative {
102107

103108
/** @type {import('./error-detection.js').ErrorDetectionSettings} */
104109
const errorDetectionSettings = {
105-
signInRequiredSelector: signInRequiredError,
110+
selectors: this.settings.selectors,
106111
testMode: this.environment.isTestMode(),
107112
callback: errorHandler,
108113
};
@@ -134,7 +139,7 @@ export class DuckPlayerNative {
134139
* @param {import('./messages.js').mediaControlSettings} settings
135140
*/
136141
mediaControlHandler({ pause }) {
137-
this.log(`Running media control handler. Pause: ${pause}`);
142+
this.logger.log('Running media control handler. Pause:', pause);
138143

139144
const videoElement = this.settings.selectors?.videoElement;
140145
const videoElementContainer = this.settings.selectors?.videoElementContainer;
@@ -159,17 +164,17 @@ export class DuckPlayerNative {
159164
* @param {import('./messages.js').muteSettings} settings
160165
*/
161166
muteAudioHandler({ mute }) {
162-
this.log(`Running mute audio handler. Mute: ${mute}`);
167+
this.logger.log('Running mute audio handler. Mute:', mute);
163168
muteAudio(mute);
164169
}
165170

166171
serpNotifyHandler() {
167-
this.log('Running SERP notify handler');
172+
this.logger.log('Running SERP notify handler');
168173
serpNotify();
169174
}
170175

171176
currentTimestampHandler() {
172-
this.log('Running current timestamp handler');
177+
this.logger.log('Running current timestamp handler');
173178
getCurrentTimestamp();
174179
}
175180
}

injected/src/features/duckplayer-native/error-detection.js

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { Logger } from './util';
2+
13
/** @typedef {"age-restricted" | "sign-in-required" | "no-embed" | "unknown"} YouTubeError */
24

35
/** @typedef {(error: YouTubeError) => void} ErrorDetectionCallback */
6+
/** @typedef {import('./duckplayer-native').DuckPlayerNativeSettings['selectors']} DuckPlayerNativeSelectors */
47

58
/**
69
* @typedef {object} ErrorDetectionSettings
7-
* @property {string} signInRequiredSelector
10+
* @property {DuckPlayerNativeSelectors} selectors
811
* @property {ErrorDetectionCallback} callback
912
* @property {boolean} testMode
1013
*/
@@ -21,8 +24,10 @@ export const YOUTUBE_ERRORS = {
2124
* Detects YouTube errors based on DOM queries
2225
*/
2326
export class ErrorDetection {
24-
/** @type {string} */
25-
signInRequiredSelector;
27+
/** @type {Logger} */
28+
logger;
29+
/** @type {DuckPlayerNativeSelectors} */
30+
selectors;
2631
/** @type {ErrorDetectionCallback} */
2732
callback;
2833
/** @type {boolean} */
@@ -31,16 +36,17 @@ export class ErrorDetection {
3136
/**
3237
* @param {ErrorDetectionSettings} settings
3338
*/
34-
constructor({ signInRequiredSelector, callback, testMode }) {
35-
this.signInRequiredSelector = signInRequiredSelector;
39+
constructor({ selectors, callback, testMode = false }) {
40+
if (!selectors?.youtubeError || !selectors?.signInRequiredError || !callback) {
41+
throw new Error('Missing selectors or callback props');
42+
}
43+
this.selectors = selectors;
3644
this.callback = callback;
3745
this.testMode = testMode;
38-
}
39-
40-
log(message, force = false) {
41-
if (this.testMode || force) {
42-
console.log(`[error-detection] ${message}`);
43-
}
46+
this.logger = new Logger({
47+
id: 'ERROR_DETECTION',
48+
shouldLog: () => this.testMode,
49+
});
4450
}
4551

4652
/**
@@ -78,10 +84,10 @@ export class ErrorDetection {
7884
*/
7985
handleError(errorId) {
8086
if (this.callback) {
81-
this.log(`Calling error handler for ${errorId}`);
87+
this.logger.log('Calling error handler for', errorId);
8288
this.callback(errorId);
8389
} else {
84-
console.warn('No error callback found');
90+
this.logger.warn('No error callback found');
8591
}
8692
}
8793

@@ -95,7 +101,7 @@ export class ErrorDetection {
95101
if (mutation.type === 'childList') {
96102
mutation.addedNodes.forEach((node) => {
97103
if (this.checkForError(node)) {
98-
console.log('A node with an error has been added to the document:', node);
104+
this.logger.log('A node with an error has been added to the document:', node);
99105
const error = this.getErrorType();
100106
this.handleError(error);
101107
}
@@ -113,18 +119,18 @@ export class ErrorDetection {
113119
let playerResponse;
114120

115121
if (!currentWindow.ytcfg) {
116-
console.log('ytcfg missing!');
122+
this.logger.warn('ytcfg missing!');
123+
} else {
124+
this.logger.log('Got ytcfg', currentWindow.ytcfg);
117125
}
118126

119-
console.log('Got ytcfg', currentWindow.ytcfg);
120-
121127
try {
122128
const playerResponseJSON = currentWindow.ytcfg?.get('PLAYER_VARS')?.embedded_player_response;
123-
console.log('Player response', playerResponseJSON);
129+
this.logger.log('Player response', playerResponseJSON);
124130

125131
playerResponse = JSON.parse(playerResponseJSON);
126132
} catch (e) {
127-
console.log('Could not parse player response', e);
133+
this.logger.log('Could not parse player response', e);
128134
}
129135

130136
if (typeof playerResponse === 'object') {
@@ -136,28 +142,28 @@ export class ErrorDetection {
136142
if (status === 'UNPLAYABLE') {
137143
// 1.1. Check for presence of desktopLegacyAgeGateReason
138144
if (desktopLegacyAgeGateReason === 1) {
139-
console.log('AGE RESTRICTED ERROR');
145+
this.logger.log('AGE RESTRICTED ERROR');
140146
return YOUTUBE_ERRORS.ageRestricted;
141147
}
142148

143149
// 1.2. Fall back to embed not allowed error
144-
console.log('NO EMBED ERROR');
150+
this.logger.log('NO EMBED ERROR');
145151
return YOUTUBE_ERRORS.noEmbed;
146152
}
147153

148154
// 2. Check for sign-in support link
149155
try {
150-
if (this.signInRequiredSelector && !!document.querySelector(this.signInRequiredSelector)) {
151-
console.log('SIGN-IN ERROR');
156+
if (document.querySelector(this.selectors.signInRequiredError)) {
157+
this.logger.log('SIGN-IN ERROR');
152158
return YOUTUBE_ERRORS.signInRequired;
153159
}
154160
} catch (e) {
155-
console.log('Sign-in required query failed', e);
161+
this.logger.log('Sign-in required query failed', e);
156162
}
157163
}
158164

159165
// 3. Fall back to unknown error
160-
console.log('UNKNOWN ERROR');
166+
this.logger.log('UNKNOWN ERROR');
161167
return YOUTUBE_ERRORS.unknown;
162168
}
163169

@@ -168,9 +174,10 @@ export class ErrorDetection {
168174
*/
169175
checkForError(node) {
170176
if (node?.nodeType === Node.ELEMENT_NODE) {
177+
const { youtubeError } = this.selectors;
171178
const element = /** @type {HTMLElement} */ (node);
172179
// Check if element has the error class or contains any children with that class
173-
const isError = element.classList.contains('ytp-error') || !!element.querySelector('.ytp-error');
180+
const isError = element.matches(youtubeError) || !!element.querySelector(youtubeError);
174181
return isError;
175182
}
176183

0 commit comments

Comments
 (0)