Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Merge pull request #46 from brave/top500-ad-insertions
Browse files Browse the repository at this point in the history
Top500 ad insertions
  • Loading branch information
bbondy committed Dec 11, 2015
2 parents 2e73b03 + 6f20ba1 commit 5a63762
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 15 deletions.
123 changes: 123 additions & 0 deletions app/content/webviewPreload.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,126 @@ ipc.on('zoom-reset', function () {
browserZoomLevel = 0
webFrame.setZoomLevel(browserZoomLevel)
})

/**
* Ensures a node replacement div is visible and has a proper zIndex
*/
function ensureNodeVisible (node) {
if (document.defaultView.getComputedStyle(node).display === 'none') {
node.style.display = ''
}
if (document.defaultView.getComputedStyle(node).zIndex === '-1') {
node.style.zIndex = ''
}
}

/**
* Determines the ad size which should be shown
* It will first check the node's size and try to infer that way.
* If that is not possible it will rely on the iframeData
*
* @param node The node that is being replaced
* @param iframeData The known preprocessed iframeData for that node
*/
function getAdSize (node, iframeData) {
var acceptableAdSizes = [
[728, 90],
[300, 250],
[160, 600],
[320, 50]
]
for (var i = 0; i < acceptableAdSizes.length; i++) {
var adSize = acceptableAdSizes[i]
if (node.offsetWidth === adSize[0] && node.offsetHeight >= adSize[1] ||
node.offsetWidth >= adSize[0] && node.offsetHeight === adSize[1]) {
return adSize
}
}

if (iframeData) {
return [iframeData.width, iframeData.height]
}

return null
}

/**
* Processes a single node which is an ad
*
* @param node The node of the ad to process
* @param iframeData The iframe data of the node to process from the slimerJS bot
* @param placeholderUrl The vault URL with encoded user ID and session ID to use
*/
function processAdNode (node, iframeData, placeholderUrl) {
if (!node) {
return
}

var adSize = getAdSize(node, iframeData)
// Could not determine the ad size, so just skip this replacement
if (!adSize) {
return
}
var srcUrl = placeholderUrl + '&width=' + encodeURIComponent(adSize[0]) + '&height=' + encodeURIComponent(adSize[1])
if (node.tagName === 'IFRAME') {
node.src = srcUrl
} else {
while (node.firstChild) {
node.removeChild(node.firstChild)
}
var iframe = document.createElement('iframe')
iframe.style.padding = 0
iframe.style.border = 0
iframe.style.margin = 0
iframe.style.width = adSize[0] + 'px'
iframe.style.height = adSize[1] + 'px'
iframe.src = srcUrl
node.appendChild(iframe)
ensureNodeVisible(node)
if (node.parentNode) {
ensureNodeVisible(node.parentNode)
if (node.parentNode) {
ensureNodeVisible(node.parentNode.parentNode)
}
}
}
}

// Fires when the browser has ad replacement information to give
ipc.on('set-ad-div-candidates', function (e, adDivCandidates, placeholderUrl) {
// Keep a lookup for skipped common elements
var fallbackNodeDataForCommon = {}

// Process all of the specific ad information for this page
adDivCandidates.forEach(function (iframeData) {
var selector = '[id="' + iframeData.replaceId + '"]'
var node = document.querySelector(selector)
if (!node) {
return
}

// Skip over known common elements
if (iframeData.replaceId.startsWith('google_ads_iframe_') ||
iframeData.replaceId.endsWith('__container__')) {
fallbackNodeDataForCommon[node.id] = iframeData
return
}

// Find the node and process it
processAdNode(document.querySelector(selector), iframeData, placeholderUrl)
})

// Common selectors which could be on every page
var commonSelectors = [
'[id^="google_ads_iframe_"][id$="__container__"]'
]
commonSelectors.forEach(commonSelector => {
var nodes = document.querySelectorAll(commonSelector)
if (!nodes) {
return
}
Array.from(nodes).forEach(node => {
processAdNode(node, fallbackNodeDataForCommon[node.id], placeholderUrl)
})
})
})
41 changes: 27 additions & 14 deletions js/components/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const ReactDOM = require('react-dom')
const AppActions = require('../actions/appActions')
const ImmutableComponent = require('./immutableComponent')
const cx = require('../lib/classSet.js')
const uuid = require('node-uuid')

import adInfo from '../data/adInfo.js'
import Config from '../constants/config.js'

class Frame extends ImmutableComponent {
constructor () {
Expand All @@ -17,6 +21,10 @@ class Frame extends ImmutableComponent {
return ReactDOM.findDOMNode(this.refs.webview)
}

componentDidMount () {
this.addEventListeners()
}

componentDidUpdate () {
const activeShortcut = this.props.frame.get('activeShortcut')
switch (activeShortcut) {
Expand Down Expand Up @@ -48,62 +56,67 @@ class Frame extends ImmutableComponent {
}
}

componentDidMount () {
addEventListeners () {
this.webview.addEventListener('new-window', (e) => {
console.log('new window: ' + e.url)
AppActions.newFrame({
location: e.url
})
})
this.webview.addEventListener('close', () => {
console.log('close window')
})
this.webview.addEventListener('enter-html-full-screen', () => {
console.log('enter html full screen')
})
this.webview.addEventListener('leave-html-full-screen', () => {
console.log('leave html full screen')
})
this.webview.addEventListener('page-favicon-updated', () => {
console.log('favicon updated')
})
this.webview.addEventListener('page-title-set', ({title}) => {
console.log('title set', title)
AppActions.setFrameTitle(this.props.frame, title)
})
this.webview.addEventListener('dom-ready', () => {
console.log('dom is ready')
this.webview.addEventListener('dom-ready', (event) => {
this.insertAds(event.target.src)
})
this.webview.addEventListener('load-commit', (event) => {
if (event.isMainFrame) {
let key = this.props.frame.get('key')
console.log('load committed', event.url, key)
AppActions.setLocation(event.url, key)
}
})
this.webview.addEventListener('did-start-loading', () => {
console.log('spinner start loading')
AppActions.onWebviewLoadStart(
this.props.frame)
})
this.webview.addEventListener('did-stop-loading', () => {
console.log('did stop loading')
AppActions.onWebviewLoadEnd(
this.props.frame,
this.webview.getURL())
})
this.webview.addEventListener('did-fail-load', () => {
console.log('did fail load')
})
this.webview.addEventListener('did-finish-load', () => {
console.log('did finish load')
AppActions.updateBackForwardState(
this.props.frame,
this.webview.canGoBack(),
this.webview.canGoForward())
})
}

insertAds (currentLocation) {
let host = new window.URL(currentLocation).hostname.replace('www.', '')
let adDivCandidates = adInfo[host]
if (adDivCandidates) {
// TODO: Use a real user ID and sessionID
const userId = uuid.v4()
const sessionId = uuid.v4()

const placeholderUrl = Config.vault.replacementUrl(userId) + '?' + [
`sessionId=${sessionId}`,
`tagName=IFRAME`
].join('&')
this.webview.send('set-ad-div-candidates', adDivCandidates, placeholderUrl)
}
}

goBack () {
this.webview.goBack()
}
Expand Down
6 changes: 5 additions & 1 deletion js/constants/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

var vaultHost = process.env.VAULT_HOST || 'http://localhost:3000'
// VAULT_HOST can be set to:
// https://vault.brave.com for production
// https://vault-staging.brave.com for a dev build
// http://localhost:3000 for production
var vaultHost = process.env.VAULT_HOST || 'https://vault-staging.brave.com'

export default {
zoom: {
Expand Down
Loading

0 comments on commit 5a63762

Please sign in to comment.