Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
Choose a Base Repository
hypothesis/h
40a/h
AFDudley/h
BigBlueHat/h
BinaryStars/h
CCH543/h
Cinemacloud/h
Ericgood/h
FTG-003/h
Forethinker/h
GratefulTony/h
HGldJ1966/h
JJediny/h
John-Williams/h
Laurian/h
LittleFancy/h
MattyQ/h
Mishkin2015/h
RichardLitt/h
Staffan1/h
SteelWagstaff/h
TowerBR/h
VanyTang/h
abigailricarte/h
ackermann/h
alecchap/h
alesarrett/h
alexsegura/h
almereyda/h
alon/h
andzi/h
angelicxsoul/h
ansmoh/h
apurvajalit/h
arjunvasan/h
asdevor/h
bZichett/h
badgettrg/Webmarks
balmas/h
balupton/h
bbarker/h
bennlich/h
benthor/h
blakewest/h
bogste/h
bradparks/h
brittanystoroz/h
buiquangchien/h
cdchapman/h
charblanc/h
chowsamihq/h
chr7stos/Webmarks
chrber/h
chrismPssina/h
christinaphamAD/h
cmbirk/h
codeaudit/h
coolcool21/h
cove/h
csillag/h
danjimilk/h
dannyhope/h
daredream/h
davidmcclure/h
dennisplucinik/h
dezynetechnologies/h
diegodlh/h
djcun95/h
donsequitur/h
edsu/h
eiro10/h
emckean/h
ercchy/h
eshellman/h
fangang123/h
fchasen/h
fcrimins/h
fhirsch/h
ficolo/h
fragkopoulos/h
gauravkeerthi/h
geass/h
gergely-ujvari/h
gitter-badger/h
gnott/h
gobengo/h
gorinovic/h
gus3000/h
hashin/h
helemaalbigt/h
hmstepanek/h
hwasiti/h
hylhero/h
hyperstudio/h
iHDeveloper/h
imeysam/h
jackspaceBerkeley/h
jarey/h
jasdeep/h
jason790/h
jasonzou/j
jazahn/h
jccr/h
jean/h
jeka57/h
jeremydean/h
jermnelson/h
jibe-b/h
jnishiyama/h
jojksd/h
jpadilla/h
jtremback/h
judell/h
juli-so/h
kabacs/h
karissa/h
kaushikvijay/h
kaydoh/h
kill4uk/h
klopiinas/h
klrkdekira/h
koulihong311/h
krassif/h
krstnkngs/h
leoqmp/h
linhua55/h
lucadealfaro/h
lyspooner/h
lyzadanger/h
m1yag1/h
magee/h
mambocab/h
manunymous/h
maraino/h
mari-ja/h
markbarratt/h
martinq/h
mbbaig/h
mcarv63/h
meawoppl/h
meflyup/h
metasj/h
mgasner/h
mgax/h
mollycr/h
mrchrisadams/h
mrienstra/h
mshavlovsky/h
muddasani/h
nagyist/hyphothesis-h
nagyistoce/hypothesis-h
nanxio/h
neozhangthe1/h
ningyifan/h
nkingsley/h
nlholdem/h
nlisgo/h
noscripter/h
nshkuro/h
odnodn/h
oliversauter/h
openbizgit/h
opengovfoundation/h
openstax/hypothesis-server
ouroboros8/h
pablomarti/h
pamo/h
philipn/h
philschatz/h
pinballwonder/h
plainspace/h
raowl/h
rickyhan/h
rmoorman/h
rmtsukuru/h
robertknight/h
rowhit/h
rsarxiv/h
saakaifoundry/h
samrose/h
scharf/h
shepazu/h
sherah/h
shofheinz/h
soapdog/h
ssin122/test-h
st-fresh/h
stuk88/h
sylvanmist/h
tetratorus/h
tilgovi/h
tomnar/h
trivenews/h
truthadjustr/h
utngz/h
voidfiles/h
wenchen/h
yargevad/h
yumatch/h
zshen777/h
Nothing to show
Choose a Head Repository
hypothesis/h
40a/h
AFDudley/h
BigBlueHat/h
BinaryStars/h
CCH543/h
Cinemacloud/h
Ericgood/h
FTG-003/h
Forethinker/h
GratefulTony/h
HGldJ1966/h
JJediny/h
John-Williams/h
Laurian/h
LittleFancy/h
MattyQ/h
Mishkin2015/h
RichardLitt/h
Staffan1/h
SteelWagstaff/h
TowerBR/h
VanyTang/h
abigailricarte/h
ackermann/h
alecchap/h
alesarrett/h
alexsegura/h
almereyda/h
alon/h
andzi/h
angelicxsoul/h
ansmoh/h
apurvajalit/h
arjunvasan/h
asdevor/h
bZichett/h
badgettrg/Webmarks
balmas/h
balupton/h
bbarker/h
bennlich/h
benthor/h
blakewest/h
bogste/h
bradparks/h
brittanystoroz/h
buiquangchien/h
cdchapman/h
charblanc/h
chowsamihq/h
chr7stos/Webmarks
chrber/h
chrismPssina/h
christinaphamAD/h
cmbirk/h
codeaudit/h
coolcool21/h
cove/h
csillag/h
danjimilk/h
dannyhope/h
daredream/h
davidmcclure/h
dennisplucinik/h
dezynetechnologies/h
diegodlh/h
djcun95/h
donsequitur/h
edsu/h
eiro10/h
emckean/h
ercchy/h
eshellman/h
fangang123/h
fchasen/h
fcrimins/h
fhirsch/h
ficolo/h
fragkopoulos/h
gauravkeerthi/h
geass/h
gergely-ujvari/h
gitter-badger/h
gnott/h
gobengo/h
gorinovic/h
gus3000/h
hashin/h
helemaalbigt/h
hmstepanek/h
hwasiti/h
hylhero/h
hyperstudio/h
iHDeveloper/h
imeysam/h
jackspaceBerkeley/h
jarey/h
jasdeep/h
jason790/h
jasonzou/j
jazahn/h
jccr/h
jean/h
jeka57/h
jeremydean/h
jermnelson/h
jibe-b/h
jnishiyama/h
jojksd/h
jpadilla/h
jtremback/h
judell/h
juli-so/h
kabacs/h
karissa/h
kaushikvijay/h
kaydoh/h
kill4uk/h
klopiinas/h
klrkdekira/h
koulihong311/h
krassif/h
krstnkngs/h
leoqmp/h
linhua55/h
lucadealfaro/h
lyspooner/h
lyzadanger/h
m1yag1/h
magee/h
mambocab/h
manunymous/h
maraino/h
mari-ja/h
markbarratt/h
martinq/h
mbbaig/h
mcarv63/h
meawoppl/h
meflyup/h
metasj/h
mgasner/h
mgax/h
mollycr/h
mrchrisadams/h
mrienstra/h
mshavlovsky/h
muddasani/h
nagyist/hyphothesis-h
nagyistoce/hypothesis-h
nanxio/h
neozhangthe1/h
ningyifan/h
nkingsley/h
nlholdem/h
nlisgo/h
noscripter/h
nshkuro/h
odnodn/h
oliversauter/h
openbizgit/h
opengovfoundation/h
openstax/hypothesis-server
ouroboros8/h
pablomarti/h
pamo/h
philipn/h
philschatz/h
pinballwonder/h
plainspace/h
raowl/h
rickyhan/h
rmoorman/h
rmtsukuru/h
robertknight/h
rowhit/h
rsarxiv/h
saakaifoundry/h
samrose/h
scharf/h
shepazu/h
sherah/h
shofheinz/h
soapdog/h
ssin122/test-h
st-fresh/h
stuk88/h
sylvanmist/h
tetratorus/h
tilgovi/h
tomnar/h
trivenews/h
truthadjustr/h
utngz/h
voidfiles/h
wenchen/h
yargevad/h
yumatch/h
zshen777/h
Nothing to show
Commits on Jan 04, 2016
Add a settings page to the Chrome Extension
Add a settings page and logic to communicate with the main
extension page.

The only setting currently present is an option controlling
whether Hypothesis remains activated when navigating within a
tab, which maps directly to the '<all_urls>' permission required
for this.
Add notes explaining what the 'contentSettings' permission is used for
The intention is to rework authentication in the sidebar in future
in a way that avoids the need for 3rd party cookie access in
the user agent. Once this is done, the contentSettings permission
should be removable.
Add Google Fonts to the allowed font sources in the manifest
The settings page currently serves this font from Google Fonts.
In future we'll likely bundle it with the extension so that the
settings page can be used in offline scenarios.
Avoid requiring access to all URLs on initial installation
When the extension is initially installed, avoid asking
for access to all URLs but instead just ask for the 'activeTab'
and 'tabs' permissions. This results in a less scary prompt
which asks for access to the user's browsing history but not
access to their data on all sites.

If the user navigates whilst H is active on a tab, the extension
will show the settings dialog at that point to prompt
for additional permissions.
Refactor extension settings UI to support multiple settings
Refactor the form control management logic to support multiple
settings without additional logic per setting.
Make the 'tabs' permission optional
Out of the box, ask only for the activeTab permission
which avoids asking for the user's browsing history.

Add a setting in the Hypothesis extension settings which controls
whether badge annotation counts are shown. This currently maps
1:1 with the 'tabs' permission.
Disable the contentSettings permission for the Chrome permissions spike
As part of investigating whether we can create a useful extension
that does not ask for access to the user's browsing history and all
their data, disable the contentSettings permission - since we know
that this is a permission we can avoid with refactoring of auth in the
client.
Commits on Jan 05, 2016
Update internal state correctly if H persistence is disabled
If the option to keep H active across page navigations is disabled,
reset the internal state to disabled when the user navigates
to another page.
Change the wording of the settings to explain their privacy impact
If we make these settings optional, then I think we'll need to clarify the
privacy impact briefly beneath the option label
Add a more accurate mechanism to detect when the sidebar is unloaded
Previously the extension detected that the sidebar was unloaded
by listening for chrome.tabs.onUpdated to be emitted with a 'loading'
status. However, this reports false positives since onUpdated is emitted
when subframes within a tab enter a loading state, which does not
affect the sidebar.

Instead, add a listener for the top-level frame's "unload" event
via a content script which sends a message back to the extension's
background script notifying it that the tab has been unloaded.

The background script then updates its internal state indicating that
the sidebar is no longer installed.
Expose internal tab states as window.HypothesisChromeExtension.tabSta…
…tes()

Make the internal tab ID -> state map accessible from
the Chrome dev tools inspector for the extension's background
page via `window.HypothesisChromeExtension.tabStates()`.

This is useful for examining the internal state of
the extension for debugging.
Experiment with using chrome.webNavigation to detect page navigation …
…instead of chrome.tabs

chrome.webNavigation provides finer grained notification of tab
load states than the chrome.tabs API, enabling earlier injection
of the sidebar when navigating from one page to another with
the extension enabled via the DOMContentLoaded notification.

More importantly, it can distinguish between navigations
in top-level browsing contexts vs iframes.

A downside is that for pre-rendered tabs, it can report
events for tab processes that are not yet associated
with visible tabs in the browser but that later become
visible via a chrome.webNavigation.onTabReplaced event.
Commits on Jan 06, 2016
Refactor extension persistence to decouple permissions and settings
Refactor persistence of extension settings to decouple settings
from the permissions that require.

Previously there was a 1:1 mapping between settings and required
permissions, however some settings may require multiple permissions.

Settings are now persisted locally and when changing settings,
the UI will determine which _new_ permissions are required
or which permissions can be dropped and call Chrome's APIs
accordingly.
Re-add tabs permission to manifest
For the 'Keep extension active' setting we require the tabs
permission in order to get info about a tab via chrome.tabs.get()
to inject the sidebar. This permission has the same warning
and privacy implications as 'webNavigation', so we just request both.
Avoid trying to set properties associated with hidden tabs
The chrome.webNavigation API reports events for pre-rendered tabs
which are hidden and not associated with any visible tab.

These tabs are not accessible to the chrome.tabs or
chrome.browserAction APIs so ignore them. The state for such tabs
will be updated in the chrome.tabs.onReplaced handler when the tab
is swapped in.
Mark a tab as 'ready' for injection when a user activates it
When a user activates the browser extension for a tab, we assume
that the document is already loaded and that we can inject H
immediately.

This reduces the delay in injecting H if some third-party component
on the page is taking a long time to load.
@@ -0,0 +1,73 @@
@font-face {
font-family:'Source Sans Pro';
font-style:normal;
font-weight:400;
src:local('Source Sans Pro'),local('SourceSansPro-Regular'),url(https://fonts.gstatic.com/s/sourcesanspro/v9/ODelI1aHBYDBqgeIAH2zlNzbP97U9sKh0jjxbPbfOKg.ttf) format('truetype')
}
* {
box-sizing: border-box;
}
body {
font-family: 'Source Sans Pro';
background-color: #d3d3d3;
margin-top: 0px;
margin-bottom: 0px;
}
.content {
width: 90%;
height: 100%;
margin-left: auto;
margin-right: auto;
background-color: white;
padding-top: 20px;
padding-left: 20px;
padding-right: 20px;
border-left: 1px solid #aaa;
border-right: 1px solid #aaa;
}
.settings-header {
margin-bottom: 30px;
display: flex;
}
.settings-header__title {
margin-left: 7px;
font-size: 19px;
color: #888;
}
.setting-row {
display: flex;
align-items: start;
flex-direction: row;
}
.setting-label {
cursor: pointer;
display: inline-block;
margin-left: 10px;
font-size: 16px;
}
.setting-description {
color: #888;
}
/* TODO - Import this from header.css */
.header-logo {
display:flex;
flex-direction:row;
font-size:19px;
font-weight:700;
color:#3A3A3A;
align-items:center;
letter-spacing:-.2
}
.header-logo__dot {
color:#bd1c2b
}
@@ -0,0 +1,31 @@
<head>
<title>Hypothesis Extension Settings</title>
<link rel="stylesheet" href="/content/settings.css">
<meta charset="UTF-8">
</head>
<body>
<div class="content">
<div class="settings-header">
<div class="header-logo" title="Hypothesis Logo">
hypothes<span class="header-logo__dot">.</span>is
</div>
<div class="settings-header__title"> | Settings</div>
</div>
<div class="setting-row">
<input type="checkbox" id="showAnnotationCounts">
<label for="showAnnotationCounts" class="setting-label">
Show whether pages I visit have been annotated
<p class="setting-description">When enabled the addresses of pages you visit will be sent to Hypothesis.
<a href="https://hypothes.is/privacy">More info…</a></p>
</body>
</div>
<div class="setting-row">
<input type="checkbox" id="keepActiveOnPageChange">
<label for="keepActiveOnPageChange" class="setting-label">
Keep Hypothesis active when visiting a new page
<p class="setting-description">This requires Hypothesis to have access to read pages you visit.</p>
</label>
</div>
</div>
<script src="/lib/extension-bundle.js"></script>
</body>
@@ -0,0 +1,163 @@
/**
* Provides functions to read extension-specific settings
* and display the settings dialog.
*/
var assign = require('core-js/modules/$.object-assign');
var util = require('./util');
/**
* A dictionary mapping extension settings to their current values.
* The settings must be initialized by calling init()
*/
var values = {
keepActiveOnPageChange: false,
showAnnotationCounts: false,
};
var keys = Object.keys(values).reduce(function (keys, key) {
keys[key] = key;
return keys;
}, {});
var requestFn = util.promisify(chrome.permissions.request);
var revokeFn = util.promisify(chrome.permissions.remove);
function permissionsForSettings(settings) {
var permissions = [];
var origins = [];
if (settings.keepActiveOnPageChange || settings.showAnnotationCounts) {
permissions.push('tabs', 'webNavigation');
}
if (settings.keepActiveOnPageChange) {
origins.push('<all_urls>');
}
return {
permissions: permissions,
origins: origins,
}
}
function requestPermissions(settings) {
console.log('requesting permissions', permissionsForSettings(settings));
return requestFn(permissionsForSettings(settings));
}
function removePermissions(oldSettings, newSettings) {
var oldPermissions = permissionsForSettings(oldSettings);
var newPermissions = permissionsForSettings(newSettings);
function removedItems(a, b) {
return a.filter(function (item) {
return b.indexOf(item) == -1;
});
}
var removed = {
permissions: removedItems(oldPermissions.permissions,
newPermissions.permissions),
origins: removedItems(oldPermissions.origins,
newPermissions.origins),
};
console.log('removing permissions', removed);
return revokeFn(removed);
}
function notifySettingChanged(setting, value) {
values[setting] = value;
chrome.runtime.sendMessage({
type: 'SETTING_CHANGED',
setting: setting,
value: value,
});
}
/**
* Returns a Promise for an object mapping settings keys
* to their current values.
*/
function getAll() {
return new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({
type: 'GET_SETTINGS'
}, function (response) {
resolve(response.values);
});
});
}
function installChangeHandler() {
chrome.runtime.onMessage.addListener(function (request, _, sendResponse) {
if (request.type === 'SETTING_CHANGE_REQUEST') {
var newSettings = assign({}, values);
newSettings[request.setting] = request.value;
// request any new permissions needed for this setting
requestPermissions(newSettings).then(function (granted) {
window.localStorage.setItem("settings", JSON.stringify(values));
notifySettingChanged(request.setting, request.value);
}).catch(function (err) {
console.error('Error requesting permissions for new settings', err);
});
// remove any permissions that are no longer required
removePermissions(values, newSettings).catch(function (err) {
console.error('Error revoking permissions', err);
});
} else if (request.type === 'GET_SETTINGS') {
sendResponse({values: values});
}
});
}
/** Show the extension settings dialog in a popup window.
*
* Returns a promise which resolves once the popup window has
* been dismissed.
*/
function showSettingsDialog() {
var settingsWindowId;
chrome.windows.create({
url: '/content/settings.html',
type: 'popup',
width: 600,
height: 400,
}, function (window) {
settingsWindowId = window.id;
});
return new Promise(function (resolve, reject) {
var closedListener = function (windowId) {
if (windowId === settingsWindowId) {
chrome.windows.onRemoved.removeListener(closedListener);
resolve();
}
};
chrome.windows.onRemoved.addListener(closedListener);
});
}
function init() {
installChangeHandler();
try {
// TODO - Verify here that the saved settings are consistent with
// the extension's current permissions and reset any settings
// for which we do not have sufficient permissions
var savedSettings = JSON.parse(window.localStorage.getItem("settings"));
assign(values, savedSettings);
} catch (err) {
console.error('Error loading settings', err);
}
}
module.exports = {
init: init,
showSettingsDialog: showSettingsDialog,
values: values,
getAll: getAll,
};
@@ -1,2 +1,6 @@
require('./hypothesis-chrome-extension');
require('./install');
if (location.pathname === '/content/settings.html') {
require('./settings-ui');
} else {
require('./hypothesis-chrome-extension');
require('./install');
}
Oops, something went wrong.

No commit comments for this range