Skip to content

Commit cf1d1a5

Browse files
committed
Merge branch 'ver1_0'
2 parents 00617c5 + 9405c73 commit cf1d1a5

File tree

5 files changed

+208
-50
lines changed

5 files changed

+208
-50
lines changed

background-script.js

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
let BMU = new (function(){
3+
const BMU = function(){
44

55
this.scannedBookmarks = null;
66

@@ -27,7 +27,7 @@ let BMU = new (function(){
2727
title: new this.State(),
2828
clear: function(){this.url.clear() && this.title.clear()}
2929
}
30-
}
30+
};
3131

3232
this.debug = true;
3333

@@ -173,7 +173,7 @@ let BMU = new (function(){
173173
case "update":
174174
this.print("received update request");
175175
sendResponse(result);
176-
result.ok && this.update();
176+
result.ok && this.update(request.excludes,request.allowUrlFixup);
177177
break;
178178
case "list":
179179
this.print("received scanned list request");
@@ -195,7 +195,7 @@ let BMU = new (function(){
195195
this.createBookmarkList = async function(){
196196

197197
const BM = function(bm,r,includeReplacement){
198-
const o = {};
198+
const o = { id: bm.id };
199199
if(r.url[0] && typeof r.url[1] === "string"){
200200
o.url = { "match": bm.url };
201201
if(includeReplacement){
@@ -218,7 +218,7 @@ let BMU = new (function(){
218218
let bookmarks = this.scannedBookmarks;
219219

220220
let list = [];
221-
const END = Math.min(100,bookmarks.length);
221+
const END = bookmarks.length;
222222

223223
const REPLACER = this.getReplacers();
224224

@@ -232,7 +232,11 @@ let BMU = new (function(){
232232
list.push({note:`--- and ${bookmarks.length - END} more ---`});
233233
}
234234
this.operations.running = null;
235-
browser.runtime.sendMessage({type:"list",list:list});
235+
browser.runtime.sendMessage({
236+
type:"list",
237+
operation:this.operations.type,
238+
list:list
239+
});
236240
};
237241

238242
this.parseDomain = function(url){
@@ -247,7 +251,11 @@ let BMU = new (function(){
247251

248252
this.isBookmarkATarget = function(node,ref){
249253
let rv = false;
250-
let queries = {url:this.operations.operands.url.from,title:this.operations.operands.title.from}; // This has been set earlier by this.isOpValid()
254+
let queries = {
255+
url: this.operations.operands.url.from,
256+
title: this.operations.operands.title.from
257+
}; // This has been set earlier by this.isOpValid()
258+
251259
switch(ref.options.type){
252260
case "protocol":
253261
return (/^http:/).test(node.url) && (queries.url === null || this.parseDomain(node.url).endsWith(queries.url))
@@ -299,7 +307,12 @@ let BMU = new (function(){
299307
)
300308
.finally(()=>{
301309
this.operations.running = null;
302-
browser.runtime.sendMessage({type:"scan",success:!(this.scannedBookmarks===null),length:this.scannedBookmarks?this.scannedBookmarks.length:0,domain:options.fromDomain});
310+
browser.runtime.sendMessage({
311+
type: "scan",
312+
success: !(this.scannedBookmarks===null),
313+
length: this.scannedBookmarks?this.scannedBookmarks.length:0,
314+
domain: options.fromDomain
315+
});
303316
})
304317
}
305318

@@ -316,10 +329,19 @@ let BMU = new (function(){
316329
}
317330
}
318331

332+
319333
this.isValidURL = function(url,hasNoBackslash){
320334
let rv = true;
335+
336+
function tryMakeUrl(base){
337+
try{
338+
return new URL(base)
339+
}catch(e){
340+
return null
341+
}
342+
}
321343
try{
322-
let d = new URL(url);
344+
let d = tryMakeUrl(url) || tryMakeUrl(decodeURIComponent(url));
323345
rv = !d.host.startsWith(".")
324346
&& !d.host.endsWith(".")
325347
&& d.host.indexOf("..") === -1
@@ -348,8 +370,15 @@ let BMU = new (function(){
348370
}
349371
return rv
350372
}
351-
352-
this.update = async function(){
373+
this.reformatUrl = function(url,index){
374+
try{
375+
return decodeURIComponent(url.slice(0,index)) + url.slice(index)
376+
}catch(e){
377+
// this will intentionally cause bookmarks.update() to fail
378+
return null
379+
}
380+
}
381+
this.update = async function(excludes,allowfixup){
353382

354383
if(this.scannedBookmarks === null){
355384
return
@@ -365,11 +394,15 @@ let BMU = new (function(){
365394
const CHANGES = {};
366395
CHANGES.url = replacer.url[0] && (this.operations.type === "regexp" || replacer.url[1]);
367396
CHANGES.title = this.operations.type === "regexp" && replacer.title[0] && (typeof replacer.title[1] === "string") ;
368-
397+
let exclusions = 0;
369398
let failures = [];
370399
let success = false;
371400
for(let bm of this.scannedBookmarks){
372-
401+
if(excludes.includes(bm.id)){
402+
this.operations.progress.current++;
403+
exclusions++;
404+
continue
405+
}
373406
let newProps = {};
374407
let failedURL;
375408
if(CHANGES.url){
@@ -385,11 +418,25 @@ let BMU = new (function(){
385418

386419
if(newProps.url || newProps.title){
387420
const ID = bm.id;
421+
// This path should handle an outcome where the resulting url is in
422+
// in encoded form and thus invalid. If such a scenario were to happen
423+
// then it's very likely that the url does not have a ":" in it
424+
// so use that as a simple detecting mechanism. Moreso, should
425+
// such a scenario occur, then it is likely that the correct url
426+
// was part of a query parameter
427+
if(allowfixup && newProps.url.indexOf(":") === -1){
428+
let queryIndex = newProps.url.indexOf("?");
429+
if(queryIndex > -1){
430+
newProps.url = this.reformatUrl(newProps.url,queryIndex);
431+
}else{
432+
newProps.url = this.reformatUrl(newProps.url,newProps.url.length);
433+
}
434+
}
388435
let updating = browser.bookmarks.update(ID,newProps);
389436

390437
// This error should only happen if the bookmark to be updated is no longer available when the update is being run but it was available when scanning
391438
updating
392-
.catch((e)=>(failures.push({error:`invalid id: ${ID}`}),true))
439+
.catch((e)=>(failures.push({error:e.message}),true))
393440
.finally(()=>(this.operations.progress.current++));
394441

395442
bookmarkPromises.push(updating);
@@ -399,12 +446,17 @@ let BMU = new (function(){
399446
this.operations.progress.current++
400447
}
401448
}
402-
Promise.all(bookmarkPromises)
449+
Promise.allSettled(bookmarkPromises)
403450
.then(()=>{ success = true })
404451
// If we end up in this catch it implies error in the script
405452
.catch((e)=>{ console.error(e) })
406453
.then(()=>{
407-
browser.runtime.sendMessage({type:"update",success:(success && !failures.length),length:this.operations.progress.current,failures:failures.length?failures:null});
454+
browser.runtime.sendMessage({
455+
type: "update",
456+
success: (success && !failures.length),
457+
length: this.operations.progress.current - exclusions,
458+
failures: failures.length?failures:null
459+
});
408460
this.operations.running = null;
409461
// reset() takes one "force" argument to fully reset status so we can recover from hard errors
410462
// note - success will be true if bookmark couldn't be updated due to no matching id
@@ -414,11 +466,16 @@ let BMU = new (function(){
414466

415467
browser.runtime.onMessage.addListener(this.messageHandler.bind(this));
416468

417-
})();
469+
};
470+
471+
let engine = null;
418472

419473
async function switchToOrOpenTab(){
420-
let views = await browser.extension.getViews({type:"tab"})
474+
let views = await browser.extension.getViews({type:"tab"});
421475
if(!views.length){
476+
if(!engine){
477+
engine = new BMU();
478+
}
422479
browser.tabs.create({url:"ui.html"})
423480
}else{
424481
let aTab = await views[0].browser.tabs.getCurrent()

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"manifest_version": 2,
55
"name": "bookmark batch-updater",
66
"permissions": ["bookmarks"],
7-
"version": "0.9",
7+
"version": "1.0",
88
"browser_action": {
99
"default_title": "bookmark batch-updater",
1010
"browser_style": true

ui.css

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ body > h2:first-child{ padding: 0 8ch; margin-inline: auto; }
5050

5151
#updateWarning{
5252
transition: height 200ms ease-in, opacity 200ms ease-in;
53-
background-color: rgb(100,50,50);
53+
background-color: rgb(180,70,60);
5454
padding-inline: 1ch;
5555
transform-origin: top
5656
}
@@ -64,9 +64,19 @@ body > h2:first-child{ padding: 0 8ch; margin-inline: auto; }
6464
white-space: nowrap;
6565
padding-block: 0.3em;
6666
}
67-
.listItem{ margin: 0.1em 0 }
67+
.combo,
68+
.listItem{ margin: 0.1em 0; display: flex }
69+
70+
71+
6872
.odd{ background-color: rgba(120,120,120,0.2) }
6973

74+
.listItem > input{ margin-inline: 1ch }
75+
.listItem > input:not(:checked) ~ div{
76+
opacity: 0.7;
77+
background-color: rgb(170,60,60)
78+
}
79+
7080
code{
7181
padding-inline: 0.5ch;
7282
border: 1px solid grey;
@@ -90,6 +100,8 @@ br+code{ background: rgba(100,255,100,0.3) }
90100
.textcontrols{ width:100%; background-color: rgba(100,100,100,0.4); padding: 1ch }
91101
.textcontrols input{ width: 100%; margin-block: 0.3em }
92102

103+
.combo > input{ width: unset; margin-inline: 1ch }
104+
93105
.buttonContainer{ display: flex; }
94106

95107
#protocolRadio:checked ~ .textcontrols > #domainReplace,

ui.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ <h2>Bookmark Batch-Updater</h2>
3535
<span>Search bookmark Title</span>
3636
<input id="regexpTitleFilter" type="text" placeholder="RegExp to search title"></input>
3737
<input id="regexpTitleReplace" type="text" placeholder="String to replace title match with"></input>
38+
<p class="combo"><input id="fixupCheckbox" type="checkbox"></input><label for="fixupCheckbox">Allow BBU to try to fix urls that would otherwise be invalid. Invalid URLs will result in failure during update.</label></p>
3839
</div>
3940
</div>
4041
<div class="buttonContainer">

0 commit comments

Comments
 (0)