diff --git a/browser/extensions/api/brave_rewards_api.cc b/browser/extensions/api/brave_rewards_api.cc index 6a225aab0601..ccfc8161810d 100644 --- a/browser/extensions/api/brave_rewards_api.cc +++ b/browser/extensions/api/brave_rewards_api.cc @@ -101,7 +101,8 @@ ExtensionFunction::ResponseAction BraveRewardsGetPublisherDataFunction::Run() { if (rewards_service_) { rewards_service_->GetPublisherActivityFromUrl(params->window_id, params->url, - params->favicon_url); + params->favicon_url, + params->publisher_blob); } return RespondNow(NoArguments()); } diff --git a/common/extensions/api/brave_rewards.json b/common/extensions/api/brave_rewards.json index 2be07b3e9430..a7ddc6505486 100644 --- a/common/extensions/api/brave_rewards.json +++ b/common/extensions/api/brave_rewards.json @@ -278,6 +278,10 @@ { "name": "faviconUrl", "type": "string" + }, + { + "name": "publisherBlob", + "type": "string" } ] }, diff --git a/components/brave_rewards/browser/rewards_service.h b/components/brave_rewards/browser/rewards_service.h index 9ba514111219..ec32738584c8 100644 --- a/components/brave_rewards/browser/rewards_service.h +++ b/components/brave_rewards/browser/rewards_service.h @@ -128,7 +128,11 @@ class RewardsService : public KeyedService { const GetAllBalanceReportsCallback& callback) = 0; virtual void GetCurrentBalanceReport() = 0; virtual void IsWalletCreated(const IsWalletCreatedCallback& callback) = 0; - virtual void GetPublisherActivityFromUrl(uint64_t windowId, const std::string& url, const std::string& favicon_url) = 0; + virtual void GetPublisherActivityFromUrl( + uint64_t windowId, + const std::string& url, + const std::string& favicon_url, + const std::string& publisher_blob) = 0; virtual void GetContributionAmount( const GetContributionAmountCallback& callback) = 0; virtual void GetPublisherBanner(const std::string& publisher_id) = 0; diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 8be121a2dd32..a57a792c27fc 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -1628,9 +1628,11 @@ void RewardsServiceImpl::IsWalletCreated( bat_ledger_->IsWalletCreated(callback); } -void RewardsServiceImpl::GetPublisherActivityFromUrl(uint64_t windowId, - const std::string& url, - const std::string& favicon_url) { +void RewardsServiceImpl::GetPublisherActivityFromUrl( + uint64_t windowId, + const std::string& url, + const std::string& favicon_url, + const std::string& publisher_blob) { GURL parsedUrl(url); if (!parsedUrl.is_valid()) { @@ -1660,7 +1662,8 @@ void RewardsServiceImpl::GetPublisherActivityFromUrl(uint64_t windowId, visitData.url = origin.spec(); visitData.favicon_url = favicon_url; - bat_ledger_->GetPublisherActivityFromUrl(windowId, visitData.ToJson()); + bat_ledger_->GetPublisherActivityFromUrl( + windowId, visitData.ToJson(), publisher_blob); } void RewardsServiceImpl::OnExcludedSitesChanged(const std::string& publisher_id) { diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index f3fcab236d99..2ed367305e9a 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -143,7 +143,11 @@ class RewardsServiceImpl : public RewardsService, const GetAllBalanceReportsCallback& callback) override; void GetCurrentBalanceReport() override; void IsWalletCreated(const IsWalletCreatedCallback& callback) override; - void GetPublisherActivityFromUrl(uint64_t windowId, const std::string& url, const std::string& favicon_url) override; + void GetPublisherActivityFromUrl( + uint64_t windowId, + const std::string& url, + const std::string& favicon_url, + const std::string& publisher_blob) override; void GetContributionAmount(const GetContributionAmountCallback& callback) override; void GetPublisherBanner(const std::string& publisher_id) override; void OnPublisherBanner(std::unique_ptr banner); diff --git a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts index 3602b0a33674..602591ebc143 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts @@ -17,8 +17,9 @@ export const onTabId = (tabId: number | undefined) => action(types.ON_TAB_ID, { tabId }) -export const onTabRetrieved = (tab: chrome.tabs.Tab) => action(types.ON_TAB_RETRIEVED, { - tab +export const onTabRetrieved = (tab: chrome.tabs.Tab, publisherBlob: string | undefined) => action(types.ON_TAB_RETRIEVED, { + tab, + publisherBlob }) export const onPublisherData = (windowId: number, publisher: RewardsExtension.Publisher) => action(types.ON_PUBLISHER_DATA, { diff --git a/components/brave_rewards/resources/extension/brave_rewards/background.ts b/components/brave_rewards/resources/extension/brave_rewards/background.ts index 8129e1e2f942..2f81fe09bf86 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background.ts @@ -46,12 +46,23 @@ chrome.runtime.onInstalled.addListener(function (details) { }) chrome.runtime.onStartup.addListener(function () { - chrome.storage.local.get(['is_dismissed'], function (result) { - if (result && result['is_dismissed'] === 'false') { - chrome.browserAction.setBadgeText({ - text: '1' + chrome.runtime.onConnect.addListener(function (externalPort) { + chrome.storage.local.set({ + 'rewards_panel_open': 'true' + }) + + chrome.storage.local.get(['is_dismissed'], function (result) { + if (result && result['is_dismissed'] === 'false') { + chrome.browserAction.setBadgeText({ + text: '1' + }) + } + }) + externalPort.onDisconnect.addListener(function () { + chrome.storage.local.set({ + 'rewards_panel_open': 'false' }) - } + }) }) }) diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts b/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts index 7d30c982f753..307d651d9e8b 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts @@ -5,11 +5,11 @@ import rewardsPanelActions from '../actions/rewardsPanelActions' chrome.tabs.onCreated.addListener((tab: chrome.tabs.Tab) => { - rewardsPanelActions.onTabRetrieved(tab) + rewardsPanelActions.onTabRetrieved(tab, '') }) chrome.tabs.onUpdated.addListener((tabId: number, changeInfo: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab) => { - rewardsPanelActions.onTabRetrieved(tab) + rewardsPanelActions.onTabRetrieved(tab, '') }) chrome.tabs.onActivated.addListener((activeInfo: chrome.tabs.TabActiveInfo) => { diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts b/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts index 5fb692edddc4..c710140a1c01 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background/reducers/rewards_panel_reducer.ts @@ -82,7 +82,7 @@ export const rewardsPanelReducer = (state: RewardsExtension.State | undefined, a const id = getWindowId(tab.windowId) const publishers: Record = state.publishers const publisher = publishers[id] - chrome.braveRewards.getPublisherData(tab.windowId, tab.url, tab.favIconUrl || '') + chrome.braveRewards.getPublisherData(tab.windowId, tab.url, tab.favIconUrl || '', payload.publisherBlob || '') if (!publisher || (publisher && publisher.tabUrl !== tab.url)) { if (publisher) { delete publishers[id] diff --git a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx index b37e208f7174..3099509a34d1 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx +++ b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx @@ -52,7 +52,72 @@ export class RewardsPanel extends React.Component { if (!tabs || !tabs.length) { return } - this.props.actions.onTabRetrieved(tabs[0]) + const pollTwitchPage = (tab: chrome.tabs.Tab, tabId: number, publisherBlob: string) => { + // use an interval here to monitor when the DOM has finished + // generating. clear after the data is present. + // Check every second no more than 'limit' times + // clear the interval if panel closes + + const markupMatch = '
' + + '
' + + '\"' { + let publisherBlob = '' + if (url && url.href.startsWith('https://www.twitch.tv/')) { + chrome.storage.local.get(['rewards_panel_open'], function (result) { + if (result['rewards_panel_open'] === 'true') { + pollTwitchPage(tab, tabId, publisherBlob) + } + }) + } else { + this.props.actions.onTabRetrieved(tab, publisherBlob) + } + } + let tab = tabs[0] + if (tab.url && tab.id) { + let url = new URL(tab.url) + if (url && url.host.endsWith('.twitch.tv')) { + pollData(tab, tab.id, url) + } else { + this.props.actions.onTabRetrieved(tab) + } + } else { + this.props.actions.onTabRetrieved(tabs[0]) + } }) } diff --git a/components/brave_rewards/resources/extension/brave_rewards/manifest.json b/components/brave_rewards/resources/extension/brave_rewards/manifest.json index da7a62388f49..125117fa3db4 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/manifest.json +++ b/components/brave_rewards/resources/extension/brave_rewards/manifest.json @@ -11,7 +11,8 @@ "permissions": [ "storage", "tabs", - "chrome://favicon/*" + "chrome://favicon/*", + "https://www.twitch.tv/*" ], "browser_action": { "default_popup": "brave_rewards_panel.html", diff --git a/components/definitions/chromel.d.ts b/components/definitions/chromel.d.ts index 805673eec8cd..b491b7b4fab4 100644 --- a/components/definitions/chromel.d.ts +++ b/components/definitions/chromel.d.ts @@ -15,7 +15,7 @@ declare namespace chrome.dns { declare namespace chrome.braveRewards { const createWallet: () => {} const donateToSite: (tabId: number, publisherKey: string) => {} - const getPublisherData: (windowId: number, url: string, faviconUrl: string) => {} + const getPublisherData: (windowId: number, url: string, faviconUrl: string, publisherBlob: string | undefined) => {} const getWalletProperties: () => {} const getCurrentReport: () => {} const onWalletCreated: { diff --git a/components/services/bat_ledger/bat_ledger_impl.cc b/components/services/bat_ledger/bat_ledger_impl.cc index f78082170456..b1d18b26f04d 100644 --- a/components/services/bat_ledger/bat_ledger_impl.cc +++ b/components/services/bat_ledger/bat_ledger_impl.cc @@ -271,11 +271,13 @@ void BatLedgerImpl::IsWalletCreated(IsWalletCreatedCallback callback) { std::move(callback).Run(ledger_->IsWalletCreated()); } -void BatLedgerImpl::GetPublisherActivityFromUrl(uint64_t window_id, - const std::string& visit_data) { +void BatLedgerImpl::GetPublisherActivityFromUrl( + uint64_t window_id, + const std::string& visit_data, + const std::string& publisher_blob) { ledger::VisitData visitData; if (visitData.loadFromJson(visit_data)) - ledger_->GetPublisherActivityFromUrl(window_id, visitData); + ledger_->GetPublisherActivityFromUrl(window_id, visitData, publisher_blob); } // static diff --git a/components/services/bat_ledger/bat_ledger_impl.h b/components/services/bat_ledger/bat_ledger_impl.h index b55c7efb49c6..b32047382aa9 100644 --- a/components/services/bat_ledger/bat_ledger_impl.h +++ b/components/services/bat_ledger/bat_ledger_impl.h @@ -99,8 +99,10 @@ class BatLedgerImpl : public mojom::BatLedger, void IsWalletCreated(IsWalletCreatedCallback callback) override; - void GetPublisherActivityFromUrl(uint64_t window_id, - const std::string& visit_data) override; + void GetPublisherActivityFromUrl( + uint64_t window_id, + const std::string& visit_data, + const std::string& publisher_blob) override; void GetContributionAmount( GetContributionAmountCallback callback) override; diff --git a/components/services/bat_ledger/public/interfaces/bat_ledger.mojom b/components/services/bat_ledger/public/interfaces/bat_ledger.mojom index ba4d1fe587eb..732ca0b71527 100644 --- a/components/services/bat_ledger/public/interfaces/bat_ledger.mojom +++ b/components/services/bat_ledger/public/interfaces/bat_ledger.mojom @@ -81,7 +81,8 @@ interface BatLedger { IsWalletCreated() => (bool wallet_created); - GetPublisherActivityFromUrl(uint64 window_id, string visit_data); + GetPublisherActivityFromUrl(uint64 window_id, string visit_data, + string publisher_blob); GetContributionAmount() => (double contribution_amount); GetPublisherBanner(string publisher_id) => (string banner); diff --git a/vendor/bat-native-ledger/include/bat/ledger/ledger.h b/vendor/bat-native-ledger/include/bat/ledger/ledger.h index 578ee2f4cf7d..7d795ce3ee89 100644 --- a/vendor/bat-native-ledger/include/bat/ledger/ledger.h +++ b/vendor/bat-native-ledger/include/bat/ledger/ledger.h @@ -184,7 +184,10 @@ class LEDGER_EXPORT Ledger { const ledger::PUBLISHER_EXCLUDE& exclude, uint64_t windowId) = 0; virtual void RestorePublishers() = 0; virtual bool IsWalletCreated() const = 0; - virtual void GetPublisherActivityFromUrl(uint64_t windowId, const ledger::VisitData& visit_data) = 0; + virtual void GetPublisherActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& publisher_blob) = 0; virtual void SetBalanceReportItem(ACTIVITY_MONTH month, int year, ledger::ReportType type, diff --git a/vendor/bat-native-ledger/src/bat_get_media.cc b/vendor/bat-native-ledger/src/bat_get_media.cc index d4f08112258b..4d5e146bcd78 100644 --- a/vendor/bat-native-ledger/src/bat_get_media.cc +++ b/vendor/bat-native-ledger/src/bat_get_media.cc @@ -5,6 +5,7 @@ #include "bat_get_media.h" +#include #include #include #include @@ -394,6 +395,15 @@ void BatGetMedia::savePublisherInfo(const uint64_t& duration, return; } + publisher_id += channelId; + url = publisherURL + "/videos"; + } else if (providerName == TWITCH_MEDIA_TYPE) { + publisher_id = providerName + "#author:"; + if (channelId.empty()) { + BLOG(ledger_, ledger::LogLevel::LOG_ERROR) << + "author id is missing for: " << media_key; + return; + } publisher_id += channelId; url = publisherURL + "/videos"; } @@ -407,6 +417,7 @@ void BatGetMedia::savePublisherInfo(const uint64_t& duration, ledger::VisitData updated_visit_data(visit_data); if (favIconURL.length() > 0) { + updated_visit_data.favicon_url = favIconURL; } @@ -468,7 +479,7 @@ void BatGetMedia::onMediaActivityError(const ledger::VisitData& visit_data, new_data.path = "/"; new_data.name = name; - ledger_->GetPublisherActivityFromUrl(windowId, new_data); + ledger_->GetPublisherActivityFromUrl(windowId, new_data, std::string()); } else { BLOG(ledger_, ledger::LogLevel::LOG_ERROR) << "Media activity error for " << providerType << " (name: " @@ -477,13 +488,15 @@ void BatGetMedia::onMediaActivityError(const ledger::VisitData& visit_data, } } -void BatGetMedia::getMediaActivityFromUrl(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType) { +void BatGetMedia::getMediaActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob) { if (providerType == YOUTUBE_MEDIA_TYPE) { processYoutubeMediaPanel(windowId, visit_data, providerType); } else if (providerType == TWITCH_MEDIA_TYPE) { - processTwitchMediaPanel(windowId, visit_data, providerType); + processTwitchMediaPanel(windowId, visit_data, providerType, publisher_blob); } else { onMediaActivityError(visit_data, providerType, windowId); } @@ -503,11 +516,6 @@ void BatGetMedia::processYoutubeMediaPanel(uint64_t windowId, } } -void BatGetMedia::processTwitchMediaPanel(uint64_t windowId, - const ledger::VisitData& visit_data, const std::string& providerType) { - // TODO add support for twitch -} - void BatGetMedia::processYoutubeWatchPath(uint64_t windowId, const ledger::VisitData& visit_data, const std::string& providerType) { @@ -518,7 +526,7 @@ void BatGetMedia::processYoutubeWatchPath(uint64_t windowId, ledger_->GetMediaPublisherInfo(media_key, std::bind(&BatGetMedia::onMediaPublisherActivity, this, _1, _2, windowId, visit_data, - providerType, media_key, media_id)); + providerType, media_key, media_id, std::string())); } else { onMediaActivityError(visit_data, providerType, windowId); } @@ -534,14 +542,13 @@ void BatGetMedia::processYoutubeChannelPath(uint64_t windowId, fetchPublisherDataFromDB(windowId, visit_data, providerType, - publisher_key); + publisher_key, + std::string()); } else { onMediaActivityError(visit_data, providerType, windowId); } } - - void BatGetMedia::onMediaUserActivity(ledger::Result result, std::unique_ptr info, uint64_t windowId, @@ -566,7 +573,8 @@ void BatGetMedia::onMediaUserActivity(ledger::Result result, _3)); } else { - fetchPublisherDataFromDB(windowId, visit_data, providerType, info->id); + fetchPublisherDataFromDB(windowId, visit_data, + providerType, info->id, std::string()); } } @@ -587,10 +595,12 @@ void BatGetMedia::processYoutubeUserPath(uint64_t windowId, } } -void BatGetMedia::fetchPublisherDataFromDB(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType, - const std::string& publisher_key) { +void BatGetMedia::fetchPublisherDataFromDB( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_key, + const std::string& publisher_blob) { auto filter = ledger_->CreateActivityFilter( publisher_key, ledger::ACTIVITY_MONTH::ANY, @@ -601,16 +611,20 @@ void BatGetMedia::fetchPublisherDataFromDB(uint64_t windowId, true); ledger_->GetPanelPublisherInfo(filter, std::bind(&BatGetMedia::onFetchPublisherFromDBResponse, - this, _1, _2, windowId, visit_data, providerType, publisher_key)); + this, _1, _2, windowId, visit_data, providerType, + publisher_key, publisher_blob)); } -void BatGetMedia::onFetchPublisherFromDBResponse(ledger::Result result, - std::unique_ptr info, - uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType, - const std::string& publisher_key) { - if (result == ledger::Result::NOT_FOUND) { +void BatGetMedia::onFetchPublisherFromDBResponse( + ledger::Result result, + std::unique_ptr info, + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_key, + const std::string& publisher_blob) { + if (!info || (result == ledger::Result::NOT_FOUND && + providerType == YOUTUBE_MEDIA_TYPE)) { fetchDataFromUrl(visit_data.url, std::bind(&BatGetMedia::onGetChannelHeadlineVideo, this, windowId, @@ -620,6 +634,20 @@ void BatGetMedia::onFetchPublisherFromDBResponse(ledger::Result result, _2, _3)); } else { + if (providerType == TWITCH_MEDIA_TYPE) { + if (info->name != visit_data.name) { + std::string media_id = getTwitchMediaIdFromUrl( + visit_data, publisher_blob); + std::transform(media_id.begin(), media_id.end(), + media_id.begin(), ::tolower); + std::string media_key = getTwitchMediaKeyFromUrl(providerType, media_id, + visit_data.url); + info->name = getUserFacingHandle(publisher_blob); + savePublisherInfo(0, media_key, providerType, visit_data.url, + info->name, visit_data, windowId, info->favicon_url, + media_id); + } + } ledger_->OnPublisherActivity(result, std::move(info), windowId); } } @@ -650,7 +678,7 @@ void BatGetMedia::onGetChannelIdFromUserPage(uint64_t windowId, new_data.name = ""; new_data.favicon_url = ""; - getMediaActivityFromUrl(windowId, new_data, providerType); + getMediaActivityFromUrl(windowId, new_data, providerType, std::string()); } else { onMediaActivityError(visit_data, providerType, windowId); } @@ -687,13 +715,71 @@ void BatGetMedia::onGetChannelHeadlineVideo(uint64_t windowId, } } +void BatGetMedia::processTwitchMediaPanel( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob) { + if (!publisher_blob.empty()) { + std::string media_id = getTwitchMediaIdFromUrl(visit_data, publisher_blob); + std::transform(media_id.begin(), media_id.end(), media_id.begin(), ::tolower); + std::string media_key = getTwitchMediaKeyFromUrl(providerType, media_id, + visit_data.url); + if (!media_key.empty() && !media_id.empty()) { + ledger_->GetMediaPublisherInfo(media_key, + std::bind(&BatGetMedia::onMediaPublisherActivity, + this, _1, _2, windowId, visit_data, + providerType, media_key, media_id, publisher_blob)); + } else { + onMediaActivityError(visit_data, providerType, windowId); + } + } else { + ledger::VisitData new_visit_data(visit_data); + new_visit_data.path = std::string(); + ledger_->GetPublisherActivityFromUrl( + windowId, + new_visit_data, + std::string()); + } +} + +std::string BatGetMedia::getTwitchMediaIdFromUrl( + const ledger::VisitData& visit_data, + const std::string& publisher_blob) const { + std::string mediaId = + extractData(visit_data.url, "twitch.tv/", "/"); + if (visit_data.url.find("twitch.tv/videos/") != std::string::npos) { + mediaId = extractData(publisher_blob, + " info, uint64_t windowId, const ledger::VisitData& visit_data, const std::string& providerType, const std::string& media_key, - const std::string& media_id) { + const std::string& media_id, + const std::string& publisher_blob) { if (result != ledger::Result::LEDGER_OK && result != ledger::Result::NOT_FOUND) { @@ -702,22 +788,91 @@ void BatGetMedia::onMediaPublisherActivity(ledger::Result result, } if (!info || result == ledger::Result::NOT_FOUND) { - ledger::TwitchEventInfo twitchEventInfo; - getPublisherInfoDataCallback(media_id, - media_key, - providerType, - 0, - twitchEventInfo, - visit_data, - windowId, - result, - std::move(info)); + if (providerType == TWITCH_MEDIA_TYPE) { + // first see if we have the publisher a different way (VOD vs. livestream + ledger_->GetPublisherInfo("twitch#author:" + media_id, + std::bind(&BatGetMedia::onGetTwitchPublisherInfo, this, _1, _2, + windowId, visit_data, providerType, media_key, media_id, + publisher_blob)); + } else if (providerType == YOUTUBE_MEDIA_TYPE) { + ledger::TwitchEventInfo twitchEventInfo; + getPublisherInfoDataCallback(media_id, + media_key, + providerType, + 0, + twitchEventInfo, + visit_data, + windowId, + result, + std::move(info)); + } + } else { + if (providerType == TWITCH_MEDIA_TYPE) { + ledger_->OnPublisherActivity(result, std::move(info), windowId); + } else if (providerType == YOUTUBE_MEDIA_TYPE) { + fetchPublisherDataFromDB(windowId, visit_data, providerType, + info->id, publisher_blob); + } + } +} +void BatGetMedia::onGetTwitchPublisherInfo( + ledger::Result result, + std::unique_ptr publisher_info, + uint64_t windowId, + const ledger::VisitData visit_data, + const std::string& providerType, + const std::string& media_key, + const std::string& media_id, + const std::string& publisher_blob) { + if (result != ledger::Result::LEDGER_OK && + result != ledger::Result::NOT_FOUND) { + onMediaActivityError(visit_data, providerType, windowId); + return; + } + if (!publisher_info || result == ledger::Result::NOT_FOUND) { + if (providerType == TWITCH_MEDIA_TYPE) { + std::string publisher_name; + std::string publisher_favicon_url; + updateTwitchPublisherData(publisher_name, publisher_favicon_url, + publisher_blob); + savePublisherInfo(0, media_key, providerType, visit_data.url, + publisher_name, visit_data, windowId, publisher_favicon_url, + media_id); + } } else { - fetchPublisherDataFromDB(windowId, visit_data, providerType, info->id); + if (providerType == TWITCH_MEDIA_TYPE) { + ledger_->OnPublisherActivity(result, std::move(publisher_info), windowId); + } } } +void BatGetMedia::updateTwitchPublisherData( + std::string& publisher_name, + std::string& publisher_favicon_url, + const std::string& publisher_blob) { + publisher_name = getUserFacingHandle(publisher_blob); + publisher_favicon_url = getFaviconUrl(publisher_blob, publisher_name); +} + +std::string BatGetMedia::getUserFacingHandle( + const std::string& publisher_blob) const { + return extractData(publisher_blob, + "
" + "
" + "\""," + "
" + "\"" startPos) { - match = data.substr(startPos, endPos - startPos); - } else if (endPos != std::string::npos) { - match = data.substr(startPos, endPos); + if (endPos != startPos) { + if (endPos != std::string::npos && endPos > startPos) { + match = data.substr(startPos, endPos - startPos); + } else if (endPos != std::string::npos) { + match = data.substr(startPos, endPos); + } else { + match = data.substr(startPos, std::string::npos); + } } } return match; diff --git a/vendor/bat-native-ledger/src/bat_get_media.h b/vendor/bat-native-ledger/src/bat_get_media.h index 66236a7141ec..cc72dcae2c0c 100644 --- a/vendor/bat-native-ledger/src/bat_get_media.h +++ b/vendor/bat-native-ledger/src/bat_get_media.h @@ -40,9 +40,11 @@ class BatGetMedia { const std::string& type, const ledger::VisitData& visit_data); - void getMediaActivityFromUrl(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType); + void getMediaActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob); static std::string getYoutubeMediaIdFromUrl(const ledger::VisitData& visit_data); @@ -99,13 +101,15 @@ class BatGetMedia { const std::string& providerType, uint64_t windowId); - void onMediaPublisherActivity(ledger::Result result, - std::unique_ptr info, - uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType, - const std::string& media_key, - const std::string& media_id); + void onMediaPublisherActivity( + ledger::Result result, + std::unique_ptr info, + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& media_key, + const std::string& media_id, + const std::string& publisher_blob); void onGetChannelIdFromUserPage(uint64_t windowId, const ledger::VisitData& visit_data, @@ -126,10 +130,36 @@ class BatGetMedia { const ledger::VisitData& visit_data, const std::string& providerType); - void processTwitchMediaPanel(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType); - + void processTwitchMediaPanel( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob); + std::string getTwitchMediaIdFromUrl( + const ledger::VisitData& visit_data, + const std::string& publisher_blob) const; + std::string getTwitchMediaKeyFromUrl( + const std::string& provider_type, + const std::string& id, + const std::string& url) const; + std::string getUserFacingHandle( + const std::string& publisher_blob) const; + std::string getFaviconUrl( + const std::string& publisher_blob, + const std::string& twitchHandle) const; + void onGetTwitchPublisherInfo( + ledger::Result result, + std::unique_ptr publisher_info, + uint64_t windowId, + const ledger::VisitData visit_data, + const std::string& providerType, + const std::string& media_key, + const std::string& media_id, + const std::string& publisher_blob); + void updateTwitchPublisherData( + std::string& publisher_name, + std::string& publisher_favicon_url, + const std::string& publisher_blob); void processYoutubeWatchPath(uint64_t windowId, const ledger::VisitData& visit_data, const std::string& providerType); @@ -156,12 +186,14 @@ class BatGetMedia { const std::string& response, const std::map& headers); - void onFetchPublisherFromDBResponse(ledger::Result result, - std::unique_ptr info, - uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType, - const std::string& publisher_key); + void onFetchPublisherFromDBResponse( + ledger::Result result, + std::unique_ptr info, + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_key, + const std::string& publisher_blob); void processYoutubeAsPublisherType(const std::string& data, uint64_t windowId, @@ -180,14 +212,16 @@ class BatGetMedia { std::string extractData(const std::string& data, const std::string& matchAfter, - const std::string& matchUntil); + const std::string& matchUntil) const; std::string getPublisherUrl(const std::string& publisher_key, const std::string& providerName); - void fetchPublisherDataFromDB(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType, - const std::string& publisher_key); + void fetchPublisherDataFromDB( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_key, + const std::string& publisher_blob); void fetchDataFromUrl(const std::string& url, FetchDataFromUrlCallback callback); diff --git a/vendor/bat-native-ledger/src/bat_publishers.cc b/vendor/bat-native-ledger/src/bat_publishers.cc index 99cb8ad02ef7..18f4e15c2cdc 100644 --- a/vendor/bat-native-ledger/src/bat_publishers.cc +++ b/vendor/bat-native-ledger/src/bat_publishers.cc @@ -77,12 +77,14 @@ void BatPublishers::AddRecurringPayment(const std::string& publisher_id, const d void onVisitSavedDummy(ledger::Result result, std::unique_ptr publisher_info) { + // onPublisherInfoUpdated will always be called by LedgerImpl so do nothing } void BatPublishers::saveVisit(const std::string& publisher_id, const ledger::VisitData& visit_data, - const uint64_t& duration) { + const uint64_t& duration, + uint64_t window_id) { if (!ledger_->GetRewardsMainEnabled() || publisher_id.empty()) { return; } @@ -100,7 +102,7 @@ void BatPublishers::saveVisit(const std::string& publisher_id, publisher_id, visit_data, duration, - 0, + window_id, _1, _2); ledger_->GetActivityInfo(filter, callbackGetPublishers); @@ -192,7 +194,6 @@ void BatPublishers::saveVisitInternal( // TODO error handling return; } - bool verified = isVerified(publisher_id); bool new_visit = false; @@ -204,14 +205,21 @@ void BatPublishers::saveVisitInternal( } std::string fav_icon = visit_data.favicon_url; - if (verified && fav_icon.length() > 0) { + if (verified && !fav_icon.empty()) { + if (fav_icon.find(".invalid") == std::string::npos) { ledger_->FetchFavIcon(fav_icon, "https://" + ledger_->GenerateGUID() + ".invalid", std::bind(&BatPublishers::onFetchFavIcon, this, publisher_info->id, + window_id, _1, _2)); + } else { + publisher_info->favicon_url = fav_icon; + } + } else { + publisher_info->favicon_url = std::string(); } publisher_info->name = visit_data.name; @@ -245,6 +253,7 @@ void BatPublishers::saveVisitInternal( min_duration_new || verified_new)) { panel_info = std::make_unique(*publisher_info); + ledger_->SetPublisherInfo(std::move(publisher_info), std::bind(&onVisitSavedDummy, _1, _2)); } else if (!excluded && @@ -257,6 +266,7 @@ void BatPublishers::saveVisitInternal( publisher_info->reconcile_stamp = ledger_->GetReconcileStamp(); panel_info = std::make_unique(*publisher_info); + ledger_->SetActivityInfo(std::move(publisher_info), std::bind(&onVisitSavedDummy, _1, _2)); } @@ -270,22 +280,41 @@ void BatPublishers::saveVisitInternal( } void BatPublishers::onFetchFavIcon(const std::string& publisher_key, + uint64_t window_id, bool success, const std::string& favicon_url) { + if (!success || favicon_url.empty()) { + BLOG(ledger_, ledger::LogLevel::LOG_WARNING) << + "Missing or corrupted favicon file for: " << publisher_key; + return; + } + ledger_->GetPublisherInfo(publisher_key, std::bind(&BatPublishers::onFetchFavIconDBResponse, - this, _1, _2, favicon_url)); + this, _1, _2, favicon_url, window_id)); } void BatPublishers::onFetchFavIconDBResponse( ledger::Result result, std::unique_ptr info, - const std::string& favicon_url) { + const std::string& favicon_url, + uint64_t window_id) { if (result == ledger::Result::LEDGER_OK && !favicon_url.empty()) { info->favicon_url = favicon_url; + std::unique_ptr panel_info = + std::make_unique(*info); + ledger_->SetPublisherInfo(std::move(info), std::bind(&onVisitSavedDummy, _1, _2)); + + if (window_id > 0) { + ledger::VisitData visit_data; + onPublisherActivity(ledger::Result::LEDGER_OK, + std::move(panel_info), + window_id, + visit_data); + } } else { BLOG(ledger_, ledger::LogLevel::LOG_WARNING) << "Missing or corrupted favicon file"; @@ -773,7 +802,10 @@ bool BatPublishers::loadPublisherList(const std::string& data) { return success; } -void BatPublishers::getPublisherActivityFromUrl(uint64_t windowId, const ledger::VisitData& visit_data) { +void BatPublishers::getPublisherActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& publisher_blob) { if ((visit_data.domain == YOUTUBE_TLD || visit_data.domain == TWITCH_TLD) && visit_data.path != "" && visit_data.path != "/") { std::string type = YOUTUBE_MEDIA_TYPE; @@ -789,7 +821,8 @@ void BatPublishers::getPublisherActivityFromUrl(uint64_t windowId, const ledger: new_visit_data.url = new_visit_data.url + new_visit_data.path; - ledger_->GetMediaActivityFromUrl(windowId, new_visit_data, type); + ledger_->GetMediaActivityFromUrl( + windowId, new_visit_data, type, publisher_blob); return; } diff --git a/vendor/bat-native-ledger/src/bat_publishers.h b/vendor/bat-native-ledger/src/bat_publishers.h index 531e80bb02a9..ecfaf3b671c6 100644 --- a/vendor/bat-native-ledger/src/bat_publishers.h +++ b/vendor/bat-native-ledger/src/bat_publishers.h @@ -37,7 +37,8 @@ class BatPublishers : public ledger::LedgerCallbackHandler { void saveVisit(const std::string& publisher_id, const ledger::VisitData& visit_data, - const uint64_t& duration); + const uint64_t& duration, + uint64_t window_id); void AddRecurringPayment(const std::string& publisher_id, const double& value); @@ -84,7 +85,10 @@ class BatPublishers : public ledger::LedgerCallbackHandler { bool loadPublisherList(const std::string& data); - void getPublisherActivityFromUrl(uint64_t windowId,const ledger::VisitData& visit_data); + void getPublisherActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& publisher_blob); void getPublisherBanner(const std::string& publisher_id, ledger::PublisherBannerCallback callback); @@ -150,12 +154,14 @@ class BatPublishers : public ledger::LedgerCallbackHandler { std::unique_ptr publisher_info); void onFetchFavIcon(const std::string& publisher_key, + uint64_t window_id, bool success, const std::string& favicon_url); void onFetchFavIconDBResponse(ledger::Result result, std::unique_ptr info, - const std::string& favicon_url); + const std::string& favicon_url, + uint64_t window_id); void setNumExcludedSitesInternal(ledger::PUBLISHER_EXCLUDE exclude); diff --git a/vendor/bat-native-ledger/src/ledger_impl.cc b/vendor/bat-native-ledger/src/ledger_impl.cc index fb4f43c62a0f..9276ae54148f 100644 --- a/vendor/bat-native-ledger/src/ledger_impl.cc +++ b/vendor/bat-native-ledger/src/ledger_impl.cc @@ -116,7 +116,8 @@ void LedgerImpl::OnHide(uint32_t tab_id, const uint64_t& current_time) { return; } DCHECK(last_tab_active_time_); - bat_publishers_->saveVisit(iter->second.tld, iter->second, current_time - last_tab_active_time_); + bat_publishers_->saveVisit( + iter->second.tld, iter->second, current_time - last_tab_active_time_, 0); last_tab_active_time_ = 0; } @@ -333,7 +334,7 @@ void LedgerImpl::SaveMediaVisit(const std::string& publisher_id, const uint64_t& duration, const uint64_t window_id) { if (bat_publishers_->getPublisherAllowVideos()) { - bat_publishers_->saveVisit(publisher_id, visit_data, duration); + bat_publishers_->saveVisit(publisher_id, visit_data, duration, window_id); } } @@ -800,15 +801,23 @@ bool LedgerImpl::IsWalletCreated() const { return bat_state_->IsWalletCreated(); } -void LedgerImpl::GetPublisherActivityFromUrl(uint64_t windowId, - const ledger::VisitData& visit_data) { - bat_publishers_->getPublisherActivityFromUrl(windowId, visit_data); +void LedgerImpl::GetPublisherActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& publisher_blob) { + bat_publishers_->getPublisherActivityFromUrl( + windowId, + visit_data, + publisher_blob); } -void LedgerImpl::GetMediaActivityFromUrl(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType) { - bat_get_media_->getMediaActivityFromUrl(windowId, visit_data, providerType); +void LedgerImpl::GetMediaActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob) { + bat_get_media_->getMediaActivityFromUrl( + windowId, visit_data, providerType, publisher_blob); } void LedgerImpl::OnPublisherActivity(ledger::Result result, diff --git a/vendor/bat-native-ledger/src/ledger_impl.h b/vendor/bat-native-ledger/src/ledger_impl.h index ec5dd324939a..fec7da811105 100644 --- a/vendor/bat-native-ledger/src/ledger_impl.h +++ b/vendor/bat-native-ledger/src/ledger_impl.h @@ -168,10 +168,15 @@ class LedgerImpl : public ledger::Ledger, void RestorePublishers() override; void OnRestorePublishers(ledger::OnRestoreCallback callback); bool IsWalletCreated() const override; - void GetPublisherActivityFromUrl(uint64_t windowId, const ledger::VisitData& visit_data) override; - void GetMediaActivityFromUrl(uint64_t windowId, - const ledger::VisitData& visit_data, - const std::string& providerType); + void GetPublisherActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& publisher_blob) override; + void GetMediaActivityFromUrl( + uint64_t windowId, + const ledger::VisitData& visit_data, + const std::string& providerType, + const std::string& publisher_blob); void OnPublisherActivity(ledger::Result result, std::unique_ptr info, uint64_t windowId);