Skip to content
This repository was archived by the owner on Dec 29, 2021. It is now read-only.

Commit 8d77bc0

Browse files
committed
Usability improvements around OAuth, better logging.
1 parent 839a393 commit 8d77bc0

7 files changed

Lines changed: 94 additions & 74 deletions

File tree

src/_locales/de/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@
4343
"message": "Ermächtigen Google Calendar für Chrome",
4444
"description": "A message shown when the user needs to grant permission for this extension to read events from their calendar."
4545
},
46+
"authorization_in_progress": {
47+
"message": "Autorisieren…",
48+
"description": "A message shown after the user clicks on the Authorize button."
49+
},
4650
"authorization_explanation": {
4751
"message": "Google Kalender für Chrome können Sie Ihren Kalender überprüfen, während Sie andere Websites besuchen. Dazu müssen Sie es den Zugriff auf Ihren Kalender gewähren. Dies ist eine einmalige Einrichtungsschritt erforderlich, bevor Sie diese App nutzen können.",
4852
"description": "A detailed message explaining the OAuth flow."
4953
},
54+
"more_info": {
55+
"message": "Weitere Informationen…",
56+
"description": "A link that provides more information about the authorization required."
57+
},
5058
"add_to_google_calendar": {
5159
"message": "Zum Google Kalender hinzufügen",
5260
"description": "Alt text and/or link text for the link that users click to add event to their calendar."

src/_locales/en/messages.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,21 @@
5454
"description": "A message shown when the user needs to grant permission for this extension to read events from their calendar."
5555
},
5656

57+
"authorization_in_progress": {
58+
"message": "Authorizing…",
59+
"description": "A message shown after the user clicks on the Authorize button."
60+
},
61+
5762
"authorization_explanation": {
5863
"message": "Google Calendar for Chrome lets you check your calendar while you visit other websites. For this, you need to grant it access to your calendar. This is a one-time setup step required before you can use this app.",
5964
"description": "A detailed message explaining the OAuth flow."
6065
},
6166

67+
"more_info": {
68+
"message": "More information…",
69+
"description": "A link that provides more information about the authorization required."
70+
},
71+
6272
"add_to_google_calendar": {
6373
"message": "Add to Google Calendar",
6474
"description": "Alt text and/or link text for the link that users click to add event to their calendar."

src/_locales/es/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@
4343
"message": "Autorizar a Google Calendar para Chrome",
4444
"description": "A message shown when the user needs to grant permission for this extension to read events from their calendar."
4545
},
46+
"authorization_in_progress": {
47+
"message": "Autorizando…",
48+
"description": "A message shown after the user clicks on the Authorize button."
49+
},
4650
"authorization_explanation": {
4751
"message": "Google Calendar para Chrome te permite comprobar el calendario mientras usted visita otros sitios web. Para ello, es necesario darle acceso a su calendario. Este es un paso de configuración de una sola vez falta antes de poder utilizar esta aplicación.",
4852
"description": "A detailed message explaining the OAuth flow."
4953
},
54+
"more_info": {
55+
"message": "Más información…",
56+
"description": "A link that provides more information about the authorization required."
57+
},
5058
"add_to_google_calendar": {
5159
"message": "Añadir a Google Calendar",
5260
"description": "Alt text and/or link text for the link that users click to add event to their calendar."

src/browser_action.css

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ header {
3131
text-decoration: none;
3232
}
3333

34-
.action-bar {
34+
#action-bar {
3535
float: right;
3636
}
3737

38-
.action-bar img {
38+
#action-bar img {
3939
cursor: pointer;
4040
height: 24px;
4141
width: 24px;
@@ -56,6 +56,10 @@ header {
5656
width: 100%;
5757
}
5858

59+
#error p {
60+
margin-bottom: 36px;
61+
}
62+
5963
#error,
6064
#quick-add {
6165
display: none;

src/browser_action.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</head>
1313
<body>
1414
<header>
15-
<div class="action-bar">
15+
<div id="action-bar">
1616
<img src="icons/5_content_new.png" id="show_quick_add" class="i18n">
1717
<img src="icons/1_navigation_refresh.png" id="sync_now" class="i18n">
1818
<img src="icons/2_action_settings.png" id="show_options" class="i18n">
@@ -26,7 +26,11 @@
2626
<a id="announcements" href="options.html" target="_blank"></a>
2727
<div id="error">
2828
<p class="i18n" id="authorization_explanation"></p>
29-
<button class="kd-button i18n" id="authorization_required"></span>
29+
<p><button class="kd-button i18n" id="authorization_required"></button></p>
30+
<p>
31+
<a class="i18n" id="more_info" target="_blank"
32+
href="http://manas.tungare.name/software/google-calendar-for-chrome/oauth/">More info…</a>
33+
</p>
3034
</div>
3135
<div id="quick-add">
3236
<div class="date-header i18n" id="add_an_event">Add an Event</div>

src/browser_action.js

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ browseraction.fillMessages_ = function() {
8989
*/
9090
browseraction.installButtonClickHandlers_ = function() {
9191
$('#authorization_required').on('click', function() {
92+
$('#authorization_required').text(chrome.i18n.getMessage('authorization_in_progress'));
9293
chrome.extension.sendMessage({method: 'authtoken.update'});
9394
});
9495

9596
$('#show_quick_add').on('click', function() {
96-
_gaq.push(['_trackEvent', 'Quick Add', 'UI Shown']);
97+
_gaq.push(['_trackEvent', 'Quick Add', 'Shown']);
9798
$('#quick-add').slideDown(200);
9899
$('#quick-add-event-title').focus();
99100
});
@@ -105,7 +106,7 @@ browseraction.installButtonClickHandlers_ = function() {
105106
});
106107

107108
$('#show_options').on('click', function() {
108-
_gaq.push(['_trackEvent', 'Options', 'View']);
109+
_gaq.push(['_trackEvent', 'Options', 'Shown']);
109110
chrome.tabs.create({'url': 'options.html'});
110111
});
111112

@@ -125,23 +126,21 @@ browseraction.installButtonClickHandlers_ = function() {
125126
* @private
126127
*/
127128
browseraction.showLoginMessageIfNotAuthenticated_ = function() {
128-
// Check if we're authenticated or not, and display either the "Login Now"
129-
// message, or show the tab strip.
130-
if (!chrome.extension.getBackgroundPage().feeds.isAuthenticated) {
131-
_gaq.push(['_trackEvent', 'Popup', 'Not Authenticated']);
132-
browseraction.stopSpinnerRightNow();
133-
$('#error').show();
134-
$('#calendar-events').hide();
135-
136-
// If we're not authenticated, then it's fine to re-request the feed
137-
// upon explicit user interaction (i.e. opening the popup.)
138-
chrome.extension.sendMessage({method: 'events.feed.fetch'},
139-
browseraction.showEventsFromFeed_);
140-
141-
} else {
142-
$('#error').hide();
143-
$('#calendar-events').show();
144-
}
129+
chrome.identity.getAuthToken({'interactive': false}, function (authToken) {
130+
if (chrome.runtime.lastError || !authToken) {
131+
_gaq.push(['_trackEvent', 'Popup', 'Not Authenticated']);
132+
chrome.extension.getBackgroundPage().background.log('OAuth not authorized: ' +
133+
chrome.runtime.lastError.message);
134+
browseraction.stopSpinnerRightNow();
135+
$('#error').show();
136+
$('#action-bar').hide();
137+
$('#calendar-events').hide();
138+
} else {
139+
$('#error').hide();
140+
$('#action-bar').show();
141+
$('#calendar-events').show();
142+
}
143+
});
145144
};
146145

147146

@@ -215,14 +214,21 @@ browseraction.showEventsFromFeed_ = function(events) {
215214
chrome.extension.getBackgroundPage().background.log('browseraction.showEventsFromFeed_()');
216215
$('#calendar-events').empty();
217216

218-
if (!chrome.extension.getBackgroundPage().feeds.isAuthenticated) {
219-
$('#error').show();
220-
$('#calendar-events').hide();
221-
return;
222-
} else {
223-
$('#error').hide();
224-
$('#calendar-events').show();
225-
}
217+
chrome.identity.getAuthToken({'interactive': false}, function (authToken) {
218+
if (chrome.runtime.lastError || !authToken) {
219+
chrome.extension.getBackgroundPage().background.log('OAuth not authorized: ' +
220+
chrome.runtime.lastError.message);
221+
$('#error').show();
222+
$('#action-bar').hide();
223+
$('#calendar-events').hide();
224+
return;
225+
226+
} else {
227+
$('#error').hide();
228+
$('#action-bar').show();
229+
$('#calendar-events').show();
230+
}
231+
});
226232

227233
// Insert a date header for Today as the first item in the list. Any ongoing
228234
// multi-day events (i.e., started last week, ends next week) will be shown

src/feeds.js

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,6 @@ feeds.nextEvents = [];
6464
*/
6565
feeds.lastFetchedAt = null;
6666

67-
/**
68-
* Indicates whether the user has logged in to Calendar or not. This is set
69-
* whenever a fetch returns valid results or a 401 error.
70-
* @type {boolean}
71-
*/
72-
feeds.isAuthenticated = false;
73-
7467
/**
7568
* Shows a UI to request an OAuth token. This should only be called in response
7669
* to user interaction to avoid confusing the user. Since the resulting window
@@ -79,13 +72,13 @@ feeds.isAuthenticated = false;
7972
* it either.
8073
*/
8174
feeds.requestInteractiveAuthToken = function() {
82-
background.log('requestInteractiveAuthToken');
75+
background.log('feeds.requestInteractiveAuthToken()');
8376
chrome.identity.getAuthToken({'interactive': true}, function (accessToken) {
84-
if (chrome.runtime.lastError) {
85-
background.log('Error requesting new auth token: ' + chrome.runtime.lastError);
77+
if (chrome.runtime.lastError || !authToken) {
78+
_gaq.push(['_trackEvent', 'OAuth Interactive', 'Not Authorized', chrome.runtime.lastError.message]);
79+
background.log('OAuth not authorized: ' + chrome.runtime.lastError.message);
8680
return;
8781
}
88-
feeds.isAuthenticated = true;
8982
feeds.refreshUI(); // Causes the badge text to be updated.
9083
feeds.fetchCalendars();
9184
});
@@ -103,21 +96,19 @@ feeds.fetchCalendars = function() {
10396

10497
chrome.storage.local.get('calendars', function(storage) {
10598
if (chrome.runtime.lastError) {
106-
background.log('Error retrieving settings: ', chrome.runtime.lastError);
99+
background.log('Error retrieving settings: ', chrome.runtime.lastError.message);
107100
}
108101

109102
var storedCalendars = storage['calendars'] || {};
110103
chrome.identity.getAuthToken({'interactive': false}, function (authToken) {
111104
if (chrome.runtime.lastError) {
112-
_gaq.push(['_trackEvent', 'Fetch', 'Error', chrome.runtime.lastError]);
113-
feeds.isAuthenticated = false;
105+
_gaq.push(['_trackEvent', 'Fetch', 'Error', chrome.runtime.lastError.message]);
114106
chrome.extension.sendMessage({method: 'sync-icon.spinning.stop'});
115107
feeds.refreshUI();
116108
return;
117109
}
118110

119111
_gaq.push(['_trackEvent', 'Fetch', 'CalendarList']);
120-
feeds.isAuthenticated = true;
121112

122113
$.ajax(feeds.CALENDAR_LIST_API_URL_, {
123114
headers: {
@@ -156,16 +147,16 @@ feeds.fetchCalendars = function() {
156147

157148
chrome.storage.local.set({'calendars': calendars}, function() {
158149
if (chrome.runtime.lastError) {
159-
background.log('Error saving settings: ', chrome.runtime.lastError);
150+
background.log('Error saving settings: ', chrome.runtime.lastError.message);
160151
return;
161152
}
162153
feeds.fetchEvents();
163154
});
164155
},
165156
error: function(response) {
166157
chrome.extension.sendMessage({method: 'sync-icon.spinning.stop'});
158+
_gaq.push(['_trackEvent', 'Fetch', 'Error', response.statusText]);
167159
if (response.status === 401) {
168-
feeds.isAuthenticated = false;
169160
feeds.refreshUI();
170161
background.log(' - Error 401 fetching list of calendars.');
171162
chrome.identity.removeCachedAuthToken({ 'token': authToken }, function() {});
@@ -176,17 +167,6 @@ feeds.fetchCalendars = function() {
176167
}
177168
}
178169
});
179-
}).error(function(response) {
180-
_gaq.push(['_trackEvent', 'Fetch', 'Error', response.statusText]);
181-
chrome.extension.sendMessage({method: 'sync-icon.spinning.stop'});
182-
if (response.status === 401) {
183-
feeds.isAuthenticated = false;
184-
feeds.refreshUI();
185-
background.log('Error 401 fetching list of calendars.');
186-
} else {
187-
window.console.log('An unknown error was encountered in fetching the feed:',
188-
response);
189-
}
190170
});
191171
});
192172
};
@@ -206,7 +186,8 @@ feeds.fetchEvents = function() {
206186

207187
chrome.storage.local.get('calendars', function(storage) {
208188
if (chrome.runtime.lastError) {
209-
background.log('Error retrieving settings:', chrome.runtime.lastError);
189+
background.log('Error retrieving settings:', chrome.runtime.lastError.message);
190+
return;
210191
}
211192

212193
if (!storage['calendars']) {
@@ -273,15 +254,14 @@ feeds.fetchEventsFromCalendar_ = function(feed, callback) {
273254
].join('&'));
274255

275256
chrome.identity.getAuthToken({'interactive': false}, function (authToken) {
276-
if (chrome.runtime.lastError) {
277-
feeds.isAuthenticated = false;
257+
if (chrome.runtime.lastError || !authToken) {
258+
chrome.extension.getBackgroundPage().background.log('OAuth not authorized: ' +
259+
chrome.runtime.lastError.message);
278260
chrome.extension.sendMessage({method: 'sync-icon.spinning.stop'});
279261
feeds.refreshUI();
280262
return;
281263
}
282264

283-
feeds.isAuthenticated = true;
284-
285265
$.ajax(feedUrl, {
286266
headers: {
287267
'Authorization': 'Bearer ' + authToken
@@ -323,16 +303,16 @@ feeds.fetchEventsFromCalendar_ = function(feed, callback) {
323303
* obtained during the last fetch. Does not fetch new data.
324304
*/
325305
feeds.refreshUI = function() {
326-
// If the user hasn't authenticated yet, bail out. Reauthentication will
327-
// happen when the user clicks on the notice in the browser action popup.
328-
if (!feeds.isAuthenticated) {
329-
background.updateBadge({
330-
'color': background.BADGE_COLORS.ERROR,
331-
'text': '×',
332-
'title': chrome.i18n.getMessage('authorization_required')
333-
});
334-
return;
335-
}
306+
chrome.identity.getAuthToken({'interactive': false}, function (authToken) {
307+
if (chrome.runtime.lastError || !authToken) {
308+
background.updateBadge({
309+
'color': background.BADGE_COLORS.ERROR,
310+
'text': '×',
311+
'title': chrome.i18n.getMessage('authorization_required')
312+
});
313+
return;
314+
}
315+
});
336316

337317
feeds.removePastEvents_();
338318
feeds.determineNextEvents_();

0 commit comments

Comments
 (0)