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

Update logic for publishers #7439

Merged
merged 2 commits into from
Mar 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions app/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,6 @@ var quit = () => {
visit('NOOP', underscore.now(), null)
clearInterval(doneTimer)
doneWriter()
if (v2RulesetDB) {
v2RulesetDB.close()
v2RulesetDB = null
}
if (v2PublishersDB) {
v2PublishersDB.close()
v2PublishersDB = null
}
}

var boot = () => {
Expand Down Expand Up @@ -578,7 +570,11 @@ eventStore.addChangeListener(() => {
var entry, faviconURL, pattern, publisher
var location = page.url

if ((location.match(/^about/)) || ((locations[location]) && (locations[location].publisher))) return
if (location.match(/^about/)) return

location = urlFormat(underscore.pick(urlParse(location), [ 'protocol', 'host', 'hostname', 'port', 'pathname' ]))
publisher = locations[location] && locations[location].publisher
if (publisher) return updateLocation(location, publisher)

if (!page.publisher) {
try {
Expand All @@ -589,7 +585,7 @@ eventStore.addChangeListener(() => {
console.log('getPublisher error for ' + location + ': ' + ex.toString())
}
}
locations[location] = underscore.omit(page, [ 'url' ])
locations[location] = underscore.omit(page, [ 'url', 'protocol', 'faviconURL' ])
if (!page.publisher) return

publisher = page.publisher
Expand All @@ -602,6 +598,7 @@ eventStore.addChangeListener(() => {
updatePublisherInfo()
})
}
updateLocation(location, publisher)
entry = synopsis.publishers[publisher]
if ((page.protocol) && (!entry.protocol)) entry.protocol = page.protocol

Expand Down Expand Up @@ -866,6 +863,7 @@ var enable = (paymentsEnabled) => {
entries.forEach((entry) => {
locations[entry.location] = entry
publishers[publisher][entry.location] = { timestamp: entry.when, tabIds: [] }
updateLocation(entry.location, publisher)
})
})
} catch (ex) {
Expand All @@ -875,6 +873,47 @@ var enable = (paymentsEnabled) => {
})
}

/*
* update location information
*/

var updateLocationInfo = (location) => {
appActions.updateLocationInfo(locations)
}

var updateLocation = (location, publisher) => {
var updateP

if (typeof locations[location].stickyP === 'undefined') locations[location].stickyP = stickyP(publisher)
if (typeof locations[location].verified !== 'undefined') return

if (synopsis && synopsis.publishers[publisher] && (typeof synopsis.publishers[publisher].options.verified !== 'undefined')) {
locations[location].verified = synopsis.publishers[publisher].options.verified || false
updateP = true
} else {
verifiedP(publisher, (err, result) => {
if ((err) && (!err.notFound)) return

locations[location].verified = (result && result.verified) || false
updateLocationInfo(location)
})
}

if (synopsis && synopsis.publishers[publisher] && (typeof synopsis.publishers[publisher].options.exclude !== 'undefined')) {
locations[location].exclude = synopsis.publishers[publisher].options.exclude || false
updateP = true
} else {
excludeP(publisher, (err, result) => {
if ((err) && (!err.notFound)) return

locations[location].exclude = (result && result.exclude) || false
updateLocationInfo(location)
})
}

if (updateP) updateLocationInfo(location)
}

/*
* update publisher information
*/
Expand Down
93 changes: 43 additions & 50 deletions app/renderer/components/publisherToggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')
const tldjs = require('tldjs')
const ImmutableComponent = require('../../../js/components/immutableComponent')
const appActions = require('../../../js/actions/appActions')
const settings = require('../../../js/constants/settings')
const getSetting = require('../../../js/settings').getSetting
const {StyleSheet, css} = require('aphrodite')
const globalStyles = require('./styles/global')
const commonStyles = require('./styles/commonStyles')
const {getHostPattern, isHttpOrHttps} = require('../../../js/lib/urlutil')
const {getBaseUrl} = require('../../../js/lib/appUrlUtil')

const noFundVerifiedPublisherImage = require('../../extensions/brave/img/urlbar/browser_URL_fund_no_verified.svg')
const fundVerifiedPublisherImage = require('../../extensions/brave/img/urlbar/browser_URL_fund_yes_verified.svg')
Expand All @@ -23,97 +24,89 @@ class PublisherToggle extends ImmutableComponent {
this.onAuthorizePublisher = this.onAuthorizePublisher.bind(this)
}

get publisherId () {
// @cezaraugusto: publisherIds aren't limited to a domain name
// when this runs, do you think that app/extensions/brave/content/scripts/pageInformation.js has already run?

return tldjs.getDomain(this.props.url)
get locationId () {
return getBaseUrl(this.props.location)
}

get hostPattern () {
return `https?://${this.publisherId}`
get publisherId () {
return this.props.locationInfo.getIn([this.locationId, 'publisher'])
}

get hostSettings () {
// hostPattern defines it's own identifier for authorized publishers
// sites that do not match criteria would populate siteSettings
// with their default protocol, not hostPattern
return this.props.hostSettings.get(this.hostPattern)
const hostPattern = getHostPattern(this.publisherId)
return this.props.siteSettings.get(hostPattern)
}

get validPublisherSynopsis () {
// If session is clear then siteSettings is undefined and icon will never be shown,
// but synopsis may not be empty. In such cases let's check if synopsis matches current publisherId
return this.props.synopsis.map(entry => entry.get('site')).includes(this.publisherId)
// If session is clear then siteSettings is undefined and icon
// will never be shown, but synopsis may not be empty.
// In such cases let's check if synopsis matches current publisherId
return !!this.props.synopsis.map(entry => entry.get('site')).includes(this.publisherId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this changes from the regular .includes() to a double negate using !!? The double negate is great for making something is truthy (when you don't care about it's value), but in this case includes() should already be returning a bool

}

get authorizedPublisher () {
// If we can't get ledgerPayments, then it's likely that we are
// on a clean session. Let's then check for publisher's synopsis
get enabledForPaymentsPublisher () {
// All publishers will be enabled by default if AUTO_SUGGEST is ON,
// excluding publishers defined on ledger's exclusion list
const excluded = this.props.locationInfo.getIn([this.locationId, 'exclude'])
const autoSuggestSites = getSetting(settings.AUTO_SUGGEST_SITES)

// hostSettings is undefined until user hit addFunds button.
// For such cases check autoSuggestSites for eligibility.
return this.hostSettings
? this.hostSettings.get('ledgerPayments') !== false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do all hostSettings entries have a ledgerPayments field? because comparing !== false will be true if that field is undefined. you might want to change this to something like:

return this.hostSettings && typeof this.hostSettings.get('ledgerPayments') === 'boolean'
    ? this.hostSettings.get('ledgerPayments') !== false
    : this.validPublisherSynopsis || (autoSuggestSites && !excluded)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep that's intentional. Ledger only recognizes false values. So if it's not on payment list yet (no user action), field will be undefined. If other conditionals don't apply then we consider it's included for payments.

: this.validPublisherSynopsis
: this.validPublisherSynopsis || (autoSuggestSites && !excluded)
}

get verifiedPublisher () {
// @cezaraugusto: should call `verifiedP` in ledger.js and return the 2nd parameter of the callback

let verifiedPublisher
this.props.synopsis.map(publisher => {
if (publisher.get('site') === this.publisherId && publisher.get('verified') === true) {
verifiedPublisher = !!publisher
return false
}
return true
})
return verifiedPublisher
return this.props.locationInfo.getIn([this.locationId, 'verified'])
}

get visiblePublisher () {
// ledgerPaymentsShown is undefined by default until user decide to permanently hide the publisher
// ledgerPaymentsShown is undefined by default until
// user decide to permanently hide the publisher,
// so for icon to be shown it can be everything but false
const ledgerPaymentsShown = this.hostSettings && this.hostSettings.get('ledgerPaymentsShown')
return ledgerPaymentsShown !== false
return typeof ledgerPaymentsShown === 'boolean'
? ledgerPaymentsShown
: true
}

get shouldShowAddPublisherButton () {
if ((!!this.hostSettings || !!this.validPublisherSynopsis) && this.visiblePublisher) {
// Only show publisher icon if ledger is enabled
return getSetting(settings.PAYMENTS_ENABLED)
}
return false
return getSetting(settings.PAYMENTS_ENABLED) &&
isHttpOrHttps(this.props.location) &&
this.visiblePublisher
}

get l10nString () {
if (this.verifiedPublisher && !this.authorizedPublisher) {
return 'verifiedPublisher'
} else if (this.authorizedPublisher) {
return 'enabledPublisher'
let l10nData = 'disabledPublisher'
if (this.verifiedPublisher && !this.enabledForPaymentsPublisher) {
l10nData = 'verifiedPublisher'
} else if (this.enabledForPaymentsPublisher) {
l10nData = 'enabledPublisher'
}
return 'disabledPublisher'
return l10nData
}

onAuthorizePublisher () {
this.authorizedPublisher
? appActions.changeSiteSetting(this.hostPattern, 'ledgerPayments', false)
: appActions.changeSiteSetting(this.hostPattern, 'ledgerPayments', true)
const hostPattern = getHostPattern(this.publisherId)
appActions.changeSiteSetting(hostPattern, 'ledgerPayments', !this.enabledForPaymentsPublisher)
}

render () {
return this.shouldShowAddPublisherButton
? <span
data-test-id='publisherButton'
data-test-authorized={this.authorizedPublisher}
data-test-authorized={this.enabledForPaymentsPublisher}
data-test-verified={this.verifiedPublisher}
className={css(styles.addPublisherButtonContainer)}>
<button
className={
css(
commonStyles.browserButton,
!this.authorizedPublisher && this.verifiedPublisher && styles.noFundVerified,
this.authorizedPublisher && this.verifiedPublisher && styles.fundVerified,
!this.authorizedPublisher && !this.verifiedPublisher && styles.noFundUnverified,
this.authorizedPublisher && !this.verifiedPublisher && styles.fundUnverified
!this.enabledForPaymentsPublisher && this.verifiedPublisher && styles.noFundVerified,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we wanted to make this cleaner, you could do the && for the two conditions above and store in a const, like

const showNoFundVerified = !this.enabledForPaymentsPublisher && this.verifiedPublisher
// ...
css(
    showNoFundVerified && styles.noFundVerified,
)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Will take this for next refactors and just updated Wiki for future reference. Thanks

this.enabledForPaymentsPublisher && this.verifiedPublisher && styles.fundVerified,
!this.enabledForPaymentsPublisher && !this.verifiedPublisher && styles.noFundUnverified,
this.enabledForPaymentsPublisher && !this.verifiedPublisher && styles.fundUnverified
)
}
data-l10n-id={this.l10nString}
Expand Down
10 changes: 10 additions & 0 deletions docs/appActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,16 @@ Updates ledger information for the payments pane



### updateLocationInfo(locationInfo)

Updates location information for the URL bar

**Parameters**

**locationInfo**: `object`, the current location synopsis



### updatePublisherInfo(publisherInfo)

Updates publisher information for the payments pane
Expand Down
9 changes: 9 additions & 0 deletions docs/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,15 @@ WindowStore
top: number // the top position of the popup window
},
previewFrameKey: number,
locationInfo: {
[url]: {
publisher: string, // url of the publisher in question
verified: boolean, // wheter or not site is a verified publisher
exclude: boolean, // wheter or not site is in the excluded list
stickyP: boolean, // wheter or not site was added using addFunds urlbar toggle
timestamp: number // timestamp in milliseconds
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super small nitpick- would be nice to alphabetize these fields. Sublime has this sorting built in; I believe you'd need an add-on for VS Code (cc @NejcZdovc)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we should keep all properties in the state.md sorted alphabetically, so that we can easily read through it

},
publisherInfo: {
synopsis: [{
daysSpent: number, // e.g., 1
Expand Down
11 changes: 11 additions & 0 deletions js/actions/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,17 @@ const appActions = {
})
},

/**
* Updates location information for the URL bar
* @param {object} locationInfo - the current location synopsis
*/
updateLocationInfo: function (locationInfo) {
AppDispatcher.dispatch({
actionType: appConstants.APP_UPDATE_LOCATION_INFO,
locationInfo
})
},

/**
* Updates publisher information for the payments pane
* @param {object} publisherInfo - the current publisher synopsis
Expand Down
1 change: 1 addition & 0 deletions js/components/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ class Main extends ImmutableComponent {
siteSettings={this.props.appState.get('siteSettings')}
synopsis={this.props.appState.getIn(['publisherInfo', 'synopsis']) || new Immutable.Map()}
activeTabShowingMessageBox={activeTabShowingMessageBox}
locationInfo={this.props.appState.get('locationInfo')}
/>
<div className='topLevelEndButtons'>
<div className={cx({
Expand Down
35 changes: 23 additions & 12 deletions js/components/navigationBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
const React = require('react')
const Immutable = require('immutable')
const ImmutableComponent = require('./immutableComponent')
const tldjs = require('tldjs')

const cx = require('../lib/classSet')
const Button = require('./button')
Expand All @@ -16,7 +15,7 @@ const siteTags = require('../constants/siteTags')
const messages = require('../constants/messages')
const settings = require('../constants/settings')
const ipc = require('electron').ipcRenderer
const {isSourceAboutUrl} = require('../lib/appUrlUtil')
const {isSourceAboutUrl, getBaseUrl} = require('../lib/appUrlUtil')
const AddEditBookmarkHanger = require('../../app/renderer/components/addEditBookmarkHanger')
const siteUtil = require('../state/siteUtil')
const eventUtil = require('../lib/eventUtil')
Expand Down Expand Up @@ -115,16 +114,27 @@ class NavigationBar extends ImmutableComponent {
)
}

get isPublisherButtonEnabled () {
const domain = tldjs.getDomain(this.props.location)
const hostSettings = this.props.siteSettings.get(`https?://${domain}`)
const visiblePublisher = hostSettings && hostSettings.get('ledgerPaymentsShown')
const validPublisherSynopsis = this.props.synopsis.map(entry => entry.get('site')).includes(domain)
get locationId () {
return getBaseUrl(this.props.location)
}

get publisherId () {
return this.props.locationInfo.getIn([this.locationId, 'publisher']) || ''
}

if ((hostSettings || validPublisherSynopsis) && visiblePublisher !== false) {
return getSetting(settings.PAYMENTS_ENABLED) && !isSourceAboutUrl(this.props.location)
get visiblePublisher () {
// No publisher is visible if ledger is disabled
if (!getSetting(settings.PAYMENTS_ENABLED)) {
return false
}
return false
const hostPattern = UrlUtil.getHostPattern(this.publisherId)
const hostSettings = this.props.siteSettings.get(hostPattern)
const ledgerPaymentsShown = hostSettings && hostSettings.get('ledgerPaymentsShown')
return ledgerPaymentsShown !== false
}

get isPublisherButtonEnabled () {
getSetting(settings.PAYMENTS_ENABLED) && this.visiblePublisher
}

componentDidMount () {
Expand Down Expand Up @@ -239,8 +249,9 @@ class NavigationBar extends ImmutableComponent {
: <div className='endButtons'>
{
<PublisherToggle
url={this.props.location}
hostSettings={this.props.siteSettings}
location={this.props.location}
locationInfo={this.props.locationInfo}
siteSettings={this.props.siteSettings}
synopsis={this.props.synopsis}
/>
}
Expand Down
1 change: 1 addition & 0 deletions js/constants/appConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const appConstants = {
APP_IMPORT_BROWSER_DATA: _,
APP_UPDATE_LEDGER_INFO: _,
APP_LEDGER_RECOVERY_STATUS_CHANGED: _,
APP_UPDATE_LOCATION_INFO: _,
APP_UPDATE_PUBLISHER_INFO: _,
APP_SHOW_NOTIFICATION: _, /** @param {Object} detail */
APP_HIDE_NOTIFICATION: _, /** @param {string} message */
Expand Down
Loading