Skip to content

Commit

Permalink
New Tab Page WebUI: Use Profile Preferences to store page options ins…
Browse files Browse the repository at this point in the history
…tead of localStorage

This allows:
- Surfacing these preferences outside of the NTP
- Syncing / migrating the preferences
- Making the change immediately for all open NTP

Use FireWebUIListener to push data to javascript event subscribers.
Still uses render_view_host->SetWebUIProperty (like the existing NTP data), which we may port in the future to a DataSource Dictionary like the other WebUI in chromium.

Provides any data retreived or updated to redux store via redux action, but does not use redux actions to ask for a data change.

Fix brave/brave-browser#5064
petemill committed Jun 28, 2019
1 parent 4a97fbe commit 13ebde9
Showing 17 changed files with 158 additions and 30 deletions.
3 changes: 3 additions & 0 deletions browser/brave_profile_prefs.cc
Original file line number Diff line number Diff line change
@@ -120,6 +120,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {

// IPFS companion extension
registry->RegisterBooleanPref(kIPFSCompanionEnabled, false);

// New Tab Page
registry->RegisterBooleanPref(kNewTabPageShowBackgroundImage, true);
}

} // namespace brave
44 changes: 44 additions & 0 deletions browser/ui/webui/brave_new_tab_message_handler.cc
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@

#include "brave/browser/ui/webui/brave_new_tab_message_handler.h"

#include <string>

#include "base/bind.h"
#include "base/values.h"
#include "brave/browser/ui/webui/brave_new_tab_ui.h"
@@ -40,6 +42,10 @@ void BraveNewTabMessageHandler::OnJavascriptAllowed() {
pref_change_registrar_.Add(kAlternativeSearchEngineProviderInTor,
base::Bind(&BraveNewTabMessageHandler::OnPrivatePropertiesChanged,
base::Unretained(this)));
// New Tab Page preferences
pref_change_registrar_.Add(kNewTabPageShowBackgroundImage,
base::Bind(&BraveNewTabMessageHandler::OnPreferencesChanged,
base::Unretained(this)));
}

void BraveNewTabMessageHandler::OnJavascriptDisallowed() {
@@ -57,6 +63,11 @@ void BraveNewTabMessageHandler::RegisterMessages() {
base::BindRepeating(
&BraveNewTabMessageHandler::HandleToggleAlternativeSearchEngineProvider,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"saveNewTabPagePref",
base::BindRepeating(
&BraveNewTabMessageHandler::HandleSaveNewTabPagePref,
base::Unretained(this)));
}

void BraveNewTabMessageHandler::HandleInitialized(const base::ListValue* args) {
@@ -69,6 +80,34 @@ void BraveNewTabMessageHandler::HandleToggleAlternativeSearchEngineProvider(
Profile::FromWebUI(web_ui()));
}

void BraveNewTabMessageHandler::HandleSaveNewTabPagePref(
const base::ListValue* args) {
if (args->GetSize() != 2) {
LOG(ERROR) << "Invalid input";
return;
}
PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
// Collect args
std::string settingsKeyInput = args->GetList()[0].GetString();
auto settingsValue = args->GetList()[1].Clone();
// Validate args
// Note: if we introduce any non-bool settings values
// then perform this type check within the appropriate key conditionals.
if (!settingsValue.is_bool()) {
LOG(ERROR) << "Invalid value type";
return;
}
const auto settingsValueBool = settingsValue.GetBool();
std::string settingsKey;
if (settingsKeyInput == "showBackgroundImage") {
settingsKey = kNewTabPageShowBackgroundImage;
} else {
LOG(ERROR) << "Invalid setting key";
return;
}
prefs->SetBoolean(settingsKey, settingsValueBool);
}

void BraveNewTabMessageHandler::OnPrivatePropertiesChanged() {
new_tab_web_ui_->OnPrivatePropertiesChanged();
}
@@ -77,3 +116,8 @@ void BraveNewTabMessageHandler::OnStatsChanged() {
new_tab_web_ui_->OnStatsChanged();
FireWebUIListener("stats-updated");
}

void BraveNewTabMessageHandler::OnPreferencesChanged() {
new_tab_web_ui_->OnPreferencesChanged();
FireWebUIListener("preferences-changed");
}
2 changes: 2 additions & 0 deletions browser/ui/webui/brave_new_tab_message_handler.h
Original file line number Diff line number Diff line change
@@ -25,10 +25,12 @@ class BraveNewTabMessageHandler : public content::WebUIMessageHandler {
void OnJavascriptDisallowed() override;

void HandleInitialized(const base::ListValue* args);
void HandleSaveNewTabPagePref(const base::ListValue* args);
void HandleToggleAlternativeSearchEngineProvider(
const base::ListValue* args);

void OnStatsChanged();
void OnPreferencesChanged();
void OnPrivatePropertiesChanged();

PrefChangeRegistrar pref_change_registrar_;
21 changes: 21 additions & 0 deletions browser/ui/webui/brave_new_tab_ui.cc
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ void BraveNewTabUI::UpdateWebUIProperties() {
auto* render_view_host = GetRenderViewHost();
SetStatsWebUIProperties(render_view_host);
SetPrivateWebUIProperties(render_view_host);
SetPreferencesWebUIProperties(render_view_host);
}

void BraveNewTabUI::SetStatsWebUIProperties(
@@ -86,6 +87,26 @@ void BraveNewTabUI::SetPrivateWebUIProperties(
}
}

void BraveNewTabUI::SetPreferencesWebUIProperties(
content::RenderViewHost* render_view_host) {
DCHECK(IsSafeToSetWebUIProperties());
Profile* profile = Profile::FromWebUI(web_ui());
PrefService* prefs = profile->GetPrefs();
if (render_view_host) {
render_view_host->SetWebUIProperty(
"showBackgroundImage",
prefs->GetBoolean(kNewTabPageShowBackgroundImage) ? "true"
: "false");
}
}


void BraveNewTabUI::OnPreferencesChanged() {
if (IsSafeToSetWebUIProperties()) {
SetPreferencesWebUIProperties(GetRenderViewHost());
}
}

void BraveNewTabUI::OnPrivatePropertiesChanged() {
if (IsSafeToSetWebUIProperties()) {
SetPrivateWebUIProperties(GetRenderViewHost());
1 change: 1 addition & 0 deletions browser/ui/webui/brave_new_tab_ui.h
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ class BraveNewTabUI : public BasicUI {
private:
// BasicUI overrides
void UpdateWebUIProperties() override;
void SetPreferencesWebUIProperties(content::RenderViewHost* render_view_host);
void SetStatsWebUIProperties(content::RenderViewHost* render_view_host);
void SetPrivateWebUIProperties(content::RenderViewHost* render_view_host);

2 changes: 2 additions & 0 deletions common/pref_names.cc
Original file line number Diff line number Diff line change
@@ -52,3 +52,5 @@ const char kWebTorrentEnabled[] = "brave.webtorrent_enabled";
const char kHangoutsEnabled[] = "brave.hangouts_enabled";
const char kHideBraveRewardsButton[] = "brave.hide_brave_rewards_button";
const char kIPFSCompanionEnabled[] = "brave.ipfs_companion_enabled";
const char kNewTabPageShowBackgroundImage[] =
"brave.new_tab_page.show_background_image";
1 change: 1 addition & 0 deletions common/pref_names.h
Original file line number Diff line number Diff line change
@@ -46,5 +46,6 @@ extern const char kWebTorrentEnabled[];
extern const char kHangoutsEnabled[];
extern const char kHideBraveRewardsButton[];
extern const char kIPFSCompanionEnabled[];
extern const char kNewTabPageShowBackgroundImage[];

#endif // BRAVE_COMMON_PREF_NAMES_H_
5 changes: 4 additions & 1 deletion components/brave_new_tab_ui/actions/new_tab_actions.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { action } from 'typesafe-actions'

// Constants
import { types } from '../constants/new_tab_types'
import { Preferences } from '../api/preferences'

export const topSitesDataUpdated = (topSites: NewTab.Site[]) => action(types.NEW_TAB_TOP_SITES_DATA_UPDATED, {
topSites
@@ -71,4 +72,6 @@ export const showSettingsMenu = () => action(types.NEW_TAB_SHOW_SETTINGS_MENU)

export const closeSettingsMenu = () => action(types.NEW_TAB_CLOSE_SETTINGS_MENU)

export const toggleShowBackgroundImage = () => action(types.NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE)
export const preferencesUpdated = (preferences: Preferences) => action(types.NEW_TAB_PREFERENCES_UPDATED, {
preferences
})
41 changes: 41 additions & 0 deletions components/brave_new_tab_ui/api/preferences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2019 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// 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/.

//
// Manages get and set of NTP preference data
// Ensures everything to do with communication
// with the WebUI backend is all in 1 place,
// especially string keys.
//

export type Preferences = {
showBackgroundImage: boolean
}

function getWebUIBooleanVal (key: string): boolean {
return (chrome.getVariableValue(key).toLowerCase() === 'true')
}

export function getPreferences (): Promise<Preferences> {
// Note(petemill): Returning as promise allows this
// to be async even though it isn't right now.
// Enforces practice of not setting directly
// in a redux reducer.
return Promise.resolve({
showBackgroundImage: getWebUIBooleanVal('showBackgroundImage')
})
}

function sendSavePref (key: string, value: any) {
chrome.send('saveNewTabPagePref', [key, value])
}

export function saveShowBackgroundImage (value: boolean): void {
sendSavePref('showBackgroundImage', value)
}

export function addChangeListener (listener: () => void): void {
window.cr.addWebUIListener('preferences-changed', listener)
}
12 changes: 11 additions & 1 deletion components/brave_new_tab_ui/brave_new_tab.tsx
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ import { Provider } from 'react-redux'
import Theme from 'brave-ui/theme/brave-default'
import { ThemeProvider } from 'brave-ui/theme'
import * as dataFetchAPI from './api/dataFetch'
import * as preferencesAPI from './api/preferences'

// Components
import App from './components/app'

@@ -20,7 +22,7 @@ import 'emptykit.css'
import '../fonts/poppins.css'
import '../fonts/muli.css'

function initialize () {
async function initialize () {
render(
<Provider store={store}>
<ThemeProvider theme={Theme}>
@@ -31,6 +33,13 @@ function initialize () {
)
window.i18nTemplate.process(window.document, window.loadTimeData)
handleAPIEvents()
await updatePreferences()
}

async function updatePreferences () {
const preferences = await preferencesAPI.getPreferences()
const actions = dataFetchAPI.getActions()
actions.preferencesUpdated(preferences)
}

function updateStats () {
@@ -41,6 +50,7 @@ function updateStats () {
function handleAPIEvents () {
chrome.send('newTabPageInitialized', [])
window.cr.addWebUIListener('stats-updated', updateStats)
preferencesAPI.addChangeListener(updatePreferences)
}

document.addEventListener('DOMContentLoaded', initialize)
16 changes: 12 additions & 4 deletions components/brave_new_tab_ui/components/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
// Copyright (c) 2019 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// 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/.

import * as React from 'react'
import { bindActionCreators, Dispatch } from 'redux'
@@ -12,6 +13,7 @@ import NewTabPage from './newTab'

// Utils
import * as newTabActions from '../actions/new_tab_actions'
import * as PreferencesAPI from '../api/preferences'

interface Props {
actions: any
@@ -29,7 +31,13 @@ class DefaultPage extends React.Component<Props, {}> {

return this.props.newTabData.isIncognito
? <NewPrivateTabPage newTabData={newTabData} actions={actions} />
: <NewTabPage newTabData={newTabData} actions={actions} />
: (
<NewTabPage
newTabData={newTabData}
actions={actions}
saveShowBackgroundImage={PreferencesAPI.saveShowBackgroundImage}
/>
)
}
}

7 changes: 5 additions & 2 deletions components/brave_new_tab_ui/components/newTab/index.tsx
Original file line number Diff line number Diff line change
@@ -24,8 +24,9 @@ import FooterInfo from './footerInfo'
import SiteRemovalNotification from './notification'

interface Props {
actions: any
newTabData: NewTab.State
actions: any
saveShowBackgroundImage: (value: boolean) => void
}

class NewTabPage extends React.Component<Props, {}> {
@@ -63,7 +64,9 @@ class NewTabPage extends React.Component<Props, {}> {
}

toggleShowBackgroundImage = () => {
this.props.actions.toggleShowBackgroundImage()
this.props.saveShowBackgroundImage(
!this.props.newTabData.showBackgroundImage
)
}

showSettings = () => {
2 changes: 1 addition & 1 deletion components/brave_new_tab_ui/constants/new_tab_types.ts
Original file line number Diff line number Diff line change
@@ -20,5 +20,5 @@ export const enum types {
NEW_TAB_USE_ALTERNATIVE_PRIVATE_SEARCH_ENGINE = '@@newtab/NEW_TAB_USE_ALTERNATIVE_PRIVATE_SEARCH_ENGINE',
NEW_TAB_SHOW_SETTINGS_MENU = '@@newtab/NEW_TAB_SHOW_SETTINGS_MENU',
NEW_TAB_CLOSE_SETTINGS_MENU = '@@newtab/NEW_TAB_CLOSE_SETTINGS_MENU',
NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE = '@@newtab/NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE'
NEW_TAB_PREFERENCES_UPDATED = '@@newtab/NEW_TAB_PREFERENCES_UPDATED'
}
13 changes: 9 additions & 4 deletions components/brave_new_tab_ui/reducers/new_tab_reducer.tsx
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { Reducer } from 'redux'

// Constants
import { types } from '../constants/new_tab_types'
import { Preferences } from '../api/preferences'

// API
import * as gridAPI from '../api/topSites/grid'
@@ -34,10 +35,6 @@ export const newTabReducer: Reducer<NewTab.State | undefined> = (state: NewTab.S
state = { ...state, showSettings: false }
break

case types.NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE:
state = { ...state, showBackgroundImage: !state.showBackgroundImage }
break

case types.BOOKMARK_ADDED:
const topSite: NewTab.Site | undefined = state.topSites.find((site) => site.url === payload.url)
if (topSite) {
@@ -157,6 +154,14 @@ export const newTabReducer: Reducer<NewTab.State | undefined> = (state: NewTab.S
state = { ...state, useAlternativePrivateSearchEngine: payload.shouldUse }
break

case types.NEW_TAB_PREFERENCES_UPDATED:
const preferences: Preferences = payload.preferences
state = {
...state,
...preferences
}
break

default:
break
}
2 changes: 1 addition & 1 deletion components/brave_new_tab_ui/storage.ts
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ import { debounce } from '../common/debounce'
const keyName = 'new-tab-data'

const defaultState: NewTab.State = {
showBackgroundImage: true,
showBackgroundImage: false,
showSettings: false,
topSites: [],
ignoredTopSites: [],
Original file line number Diff line number Diff line change
@@ -154,9 +154,4 @@ describe('newTabActions', () => {
type: types.NEW_TAB_SHOW_SETTINGS_MENU
})
})
it('toggleShowBackgroundImage', () => {
expect(actions.toggleShowBackgroundImage()).toEqual({
type: types.NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE
})
})
})
11 changes: 0 additions & 11 deletions components/test/brave_new_tab_ui/reducers/new_tab_reducer_test.ts
Original file line number Diff line number Diff line change
@@ -352,15 +352,4 @@ describe('newTabReducer', () => {
expect(assertion).toEqual(expected)
})
})

describe('NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE', () => {
it('should toggle showBackgroundimage status to be true', () => {
const mockState = { ...fakeState, showBackgroundImage: false }
const expected = { ...mockState, showBackgroundImage: true }
const assertion = newTabReducer(mockState, {
type: types.NEW_TAB_TOGGLE_SHOW_BACKGROUND_IMAGE
})
expect(assertion).toEqual(expected)
})
})
})

0 comments on commit 13ebde9

Please sign in to comment.