Skip to content

Commit

Permalink
Fixes twitch event logging
Browse files Browse the repository at this point in the history
Resolves brave#13828

Auditors:

Test Plan:
  • Loading branch information
NejcZdovc committed Apr 16, 2018
1 parent bdd8fa3 commit 1c19218
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 29 deletions.
25 changes: 22 additions & 3 deletions app/browser/api/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -2687,12 +2687,30 @@ const onMediaRequest = (state, xhr, type, details) => {
return state
}

const tabId = details.get('tabId')
const parsed = ledgerUtil.getMediaData(xhr, type, details)
if (parsed == null) {
return state
}

if (Array.isArray(parsed)) {
parsed.forEach(data => {
if (data) {
state = module.exports.processMediaData(state, data, type, details)
}
})
} else {
state = module.exports.processMediaData(state, parsed, type, details)
}

return state
}

const processMediaData = (state, parsed, type, details) => {
let tabId = tabState.TAB_ID_NONE
if (details) {
tabId = details.get('tabId')
}

const mediaId = ledgerUtil.getMediaId(parsed, type)

if (clientOptions.loggingP) {
Expand Down Expand Up @@ -2774,7 +2792,7 @@ const onMediaRequest = (state, xhr, type, details) => {

if (_internal.verboseP) {
console.log('\ngetPublisherFromMediaProps mediaProps=' + JSON.stringify(mediaProps, null, 2) + '\nresponse=' +
JSON.stringify(response, null, 2))
JSON.stringify(response, null, 2))
}

appActions.onLedgerMediaPublisher(mediaKey, response, duration, revisited)
Expand Down Expand Up @@ -3061,7 +3079,8 @@ const getMethods = () => {
referralCheck,
roundtrip,
onFetchReferralHeaders,
onReferralRead
onReferralRead,
processMediaData
}

let privateMethods = {}
Expand Down
1 change: 0 additions & 1 deletion app/common/constants/twitchEvents.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const events = {
BUFFER_EMPTY: 'buffer-empty',
BUFFER_REFILL: 'buffer-refill',
MINUTE_WATCHED: 'minute-watched',
PLAY_MANIFEST: 'video_play_master_manifest',
PLAY_PAUSE: 'video_pause',
SEEK: 'player_click_vod_seek',
START: 'video-play',
Expand Down
28 changes: 18 additions & 10 deletions app/common/lib/ledgerUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,27 @@ const getMediaData = (xhr, type, details) => {
}
case ledgerMediaProviders.TWITCH:
{
const data = details.getIn(['uploadData', 0, 'bytes'])
if (!data) {
const uploadData = details.get('uploadData') || Immutable.List()

if (uploadData.size === 0) {
result = null
break
}

let params = uploadData.reduce((old, item) => {
const bytes = item.get('bytes')
let data = ''
if (bytes) {
data = Buffer.from(bytes).toString('utf8') || ''
}
return old + data
}, '')

if (!params || params.length === 0) {
result = null
break
}

let params = Buffer.from(data).toString('utf8') || ''
const paramQuery = queryString.parse(params)

if (!paramQuery || !paramQuery.data) {
Expand All @@ -307,13 +321,7 @@ const getMediaData = (xhr, type, details) => {
break
}

if (!Array.isArray(parsed)) {
result = null
break
}

result = parsed[0]

result = parsed
break
}
}
Expand Down
98 changes: 87 additions & 11 deletions test/unit/app/browser/api/ledgerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ describe('ledger api unit tests', function () {
let updater

// constants
const xhr = 'https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=11.338&et=21.339'
const videoId = 'youtube_kLiLOkzLetE'
const publisherKey = 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg'

Expand Down Expand Up @@ -562,8 +561,81 @@ describe('ledger api unit tests', function () {
})

describe('onMediaRequest', function () {
let processMediaDataSpy
const url = 'https://video-edge-f0f586.sjc01.hls.ttvnw.net/v1/segment/CuDNI7xCy5CGJ8g7G3thdHT26OW_DhnEuVw0tRGN-DKhJxrRTeGe...'

beforeEach(function () {
processMediaDataSpy = sinon.spy(ledgerApi, 'processMediaData')
})

afterEach(function () {
processMediaDataSpy.restore()
})

it('does nothing if input is null', function () {
const result = ledgerApi.onMediaRequest(defaultAppState)
assert.deepEqual(result.toJS(), defaultAppState.toJS())
assert(processMediaDataSpy.notCalled)
})

it('does nothing if input is null', function () {
const result = ledgerApi.onMediaRequest(defaultAppState, url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [{
bytes: new Uint8Array([])
}]
}))
assert.deepEqual(result.toJS(), defaultAppState.toJS())
assert(processMediaDataSpy.notCalled)
})

it('parsed data is single object', function () {
const result = ledgerApi.onMediaRequest(defaultAppState, url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [{
bytes: new Uint8Array([
100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105,
74, 116, 97, 87, 53, 49, 100, 71, 85, 116, 100, 50, 70, 48, 89, 50, 104, 108, 90, 67, 73, 115, 73, 110,
66, 121, 98, 51, 66, 108, 99, 110, 82, 112, 90, 88, 77, 105, 79, 110, 115, 105, 89, 50, 104, 104, 98,
109, 53, 108, 98, 67, 73, 54, 73, 110, 82, 51, 73, 110, 49, 57, 88, 81, 61, 61
])
}]
}))

assert(processMediaDataSpy.calledOnce)
assert.notDeepEqual(result.toJS(), defaultAppState.toJS())
})

it('parsed data is array of objects', function () {
const result = ledgerApi.onMediaRequest(defaultAppState, url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [{
bytes: new Uint8Array([
100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105,
74, 50, 97, 87, 82, 108, 98, 121, 49, 119, 98, 71, 70, 53, 73, 105, 119, 105, 99, 72, 74, 118, 99, 71,
86, 121, 100, 71, 108, 108, 99, 121, 73, 54, 101, 121, 74, 106, 97, 71, 70, 117, 98, 109, 86, 115, 73,
106, 111, 105, 100, 72, 99, 105, 102, 88, 48, 115, 101, 121, 74, 108, 100, 109, 86, 117, 100, 67, 73, 54,
73, 110, 90, 112, 90, 71, 86, 118, 88, 50, 86, 121, 99, 109, 57, 121, 73, 105, 119, 105, 99, 72, 74, 118,
99, 71, 86, 121, 100, 71, 108, 108, 99, 121, 73, 54, 101, 121, 74, 106, 97, 71, 70, 117, 98, 109, 86,
115, 73, 106, 111, 105, 100, 72, 99, 105, 102, 88, 49, 100
])
}]
}))

assert(processMediaDataSpy.calledTwice)
assert.notDeepEqual(result.toJS(), defaultAppState.toJS())
})
})

describe('processMediaData', function () {
let mediaSpy, saveVisitSpy

const parsedData = {
docid: 'kLiLOkzLetE',
st: '11.338',
et: '21.339'
}

const cacheAppState = defaultAppState
.setIn(['cache', 'ledgerVideos', videoId], Immutable.fromJS({
publisher: publisherKey
Expand All @@ -590,7 +662,7 @@ describe('ledger api unit tests', function () {
})

it('does nothing if input is null', function () {
const result = ledgerApi.onMediaRequest(defaultAppState)
const result = ledgerApi.processMediaData(defaultAppState)
assert.deepEqual(result.toJS(), defaultAppState.toJS())
assert(mediaSpy.notCalled)
assert(saveVisitSpy.notCalled)
Expand All @@ -614,22 +686,26 @@ describe('ledger api unit tests', function () {
tabState = savedTabState
})
it('does nothing if tab is private', function () {
const xhr2 = 'https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=20.338&et=21.339'
ledgerApi.onMediaRequest(cacheAppState, xhr2, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
const data = {
docid: 'kLiLOkzLetE',
st: '20.338',
et: '21.339'
}
ledgerApi.processMediaData(cacheAppState, data, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert(mediaSpy.notCalled)
assert(saveVisitSpy.notCalled)
})
})

it('set currentMediaKey when it is different than saved', function () {
ledgerApi.onMediaRequest(defaultAppState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
ledgerApi.processMediaData(defaultAppState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert.equal(ledgerApi.getCurrentMediaKey(), videoId)
assert(mediaSpy.calledOnce)
assert(saveVisitSpy.notCalled)
})

it('get data from cache, if we have publisher in synopsis', function () {
ledgerApi.onMediaRequest(cacheAppState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
ledgerApi.processMediaData(cacheAppState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert(mediaSpy.notCalled)
assert(saveVisitSpy.withArgs(cacheAppState, publisherKey, {
duration: 10001,
Expand All @@ -642,14 +718,14 @@ describe('ledger api unit tests', function () {
const state = defaultAppState.setIn(['cache', 'ledgerVideos', videoId], Immutable.fromJS({
publisher: publisherKey
}))
ledgerApi.onMediaRequest(state, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
ledgerApi.processMediaData(state, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert(mediaSpy.calledOnce)
assert(saveVisitSpy.notCalled)
})

it('revisited if visiting the same media in the same tab', function () {
// first call, revisit false
ledgerApi.onMediaRequest(cacheAppState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
ledgerApi.processMediaData(cacheAppState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert.equal(ledgerApi.getCurrentMediaKey(), videoId)
assert(saveVisitSpy.withArgs(cacheAppState, publisherKey, {
duration: 10001,
Expand All @@ -658,7 +734,7 @@ describe('ledger api unit tests', function () {
}).calledOnce)

// second call, revisit true
ledgerApi.onMediaRequest(cacheAppState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
ledgerApi.processMediaData(cacheAppState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 1}))
assert(mediaSpy.notCalled)
assert(saveVisitSpy.withArgs(cacheAppState, publisherKey, {
duration: 10001,
Expand All @@ -670,7 +746,7 @@ describe('ledger api unit tests', function () {
it('revisited if visiting media in the background tab', function () {
// first call, revisit false
ledgerApi.setCurrentMediaKey('11')
ledgerApi.onMediaRequest(cacheAppState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 10}))
ledgerApi.processMediaData(cacheAppState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 10}))
assert.equal(ledgerApi.getCurrentMediaKey(), '11')
assert(saveVisitSpy.withArgs(cacheAppState, publisherKey, {
duration: 10001,
Expand All @@ -690,7 +766,7 @@ describe('ledger api unit tests', function () {
}
}))

ledgerApi.onMediaRequest(badState, xhr, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 10}))
ledgerApi.processMediaData(badState, parsedData, ledgerMediaProviders.YOUTUBE, Immutable.fromJS({tabId: 10}))
assert(mediaSpy.calledOnce)
assert(saveVisitSpy.notCalled)
})
Expand Down
76 changes: 72 additions & 4 deletions test/unit/app/common/lib/ledgerUtilTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,19 +558,87 @@ describe('ledgerUtil unit test', function () {
assert.equal(result, null)
})

it('obj is parsed correctly', function () {
it('single event is parsed correctly', function () {
const result = ledgerUtil.getMediaData(url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [{
bytes: new Uint8Array([100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105, 74, 116, 97, 87, 53, 49, 100, 71, 85, 116, 100, 50, 70, 48, 89, 50, 104, 108, 90, 67, 73, 115, 73, 110, 66, 121, 98, 51, 66, 108, 99, 110, 82, 112, 90, 88, 77, 105, 79, 110, 115, 105, 89, 50, 104, 104, 98, 109, 53, 108, 98, 67, 73, 54, 73, 110, 82, 51, 73, 110, 49, 57, 88, 81, 61, 61])
bytes: new Uint8Array([
100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105,
74, 116, 97, 87, 53, 49, 100, 71, 85, 116, 100, 50, 70, 48, 89, 50, 104, 108, 90, 67, 73, 115, 73, 110,
66, 121, 98, 51, 66, 108, 99, 110, 82, 112, 90, 88, 77, 105, 79, 110, 115, 105, 89, 50, 104, 104, 98,
109, 53, 108, 98, 67, 73, 54, 73, 110, 82, 51, 73, 110, 49, 57, 88, 81, 61, 61
])
}]
}))
assert.deepEqual(result, {
assert.deepEqual(result, [{
event: twitchEvents.MINUTE_WATCHED,
properties: {
channel: 'tw'
}
})
}])
})

it('multiple events are parsed correctly', function () {
const result = ledgerUtil.getMediaData(url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [{
bytes: new Uint8Array([
100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105,
74, 50, 97, 87, 82, 108, 98, 121, 49, 119, 98, 71, 70, 53, 73, 105, 119, 105, 99, 72, 74, 118, 99, 71,
86, 121, 100, 71, 108, 108, 99, 121, 73, 54, 101, 121, 74, 106, 97, 71, 70, 117, 98, 109, 86, 115, 73,
106, 111, 105, 100, 72, 99, 105, 102, 88, 48, 115, 101, 121, 74, 108, 100, 109, 86, 117, 100, 67, 73, 54,
73, 110, 90, 112, 90, 71, 86, 118, 88, 50, 86, 121, 99, 109, 57, 121, 73, 105, 119, 105, 99, 72, 74, 118,
99, 71, 86, 121, 100, 71, 108, 108, 99, 121, 73, 54, 101, 121, 74, 106, 97, 71, 70, 117, 98, 109, 86,
115, 73, 106, 111, 105, 100, 72, 99, 105, 102, 88, 49, 100
])
}]
}))
assert.deepEqual(result, [{
event: twitchEvents.START,
properties: {
channel: 'tw'
}
}, {
event: twitchEvents.VIDEO_ERROR,
properties: {
channel: 'tw'
}
}])
})

it('multiple upload data', function () {
const result = ledgerUtil.getMediaData(url, ledgerMediaProviders.TWITCH, Immutable.fromJS({
firstPartyUrl: 'https://www.twitch.tv/videos/241926348',
uploadData: [
{
bytes: new Uint8Array([
100, 97, 116, 97, 61, 87, 51, 115, 105, 90, 88, 90, 108, 98, 110, 81, 105, 79, 105, 74, 50, 97, 87,
82, 108, 98, 121, 49, 119, 98, 71, 70, 53, 73, 105, 119, 105, 99
])
},
{
bytes: new Uint8Array([
72, 74, 118, 99, 71, 86, 121, 100, 71, 108, 108, 99, 121, 73, 54, 101, 121, 74,
106, 97, 71, 70, 117, 98, 109, 86, 115, 73, 106, 111, 105, 100, 72, 99, 105, 102, 88, 48, 115, 101,
121, 74, 108, 100, 109, 86, 117, 100, 67, 73, 54, 73, 110, 90, 112, 90, 71, 86, 118, 88, 50, 86, 121,
99, 109, 57, 121, 73, 105, 119, 105, 99, 72, 74, 118, 99, 71, 86, 121, 100, 71, 108, 108, 99, 121,
73, 54, 101, 121, 74, 106, 97, 71, 70, 117, 98, 109, 86, 115, 73, 106, 111, 105, 100, 72, 99, 105,
102, 88, 49, 100
])
}
]
}))
assert.deepEqual(result, [{
event: twitchEvents.START,
properties: {
channel: 'tw'
}
}, {
event: twitchEvents.VIDEO_ERROR,
properties: {
channel: 'tw'
}
}])
})
})
})
Expand Down

0 comments on commit 1c19218

Please sign in to comment.