SpeechSynthesis.getVoices() not listing voices in Firefox - javascript

I am developing an application that requires me to use text to speech in the web browser. I am using the HTML5 Speech Synthesis for it. On Google Chrome the code runs fine, with all the available voices being listed using |getVoices()|, but in Firefox no voice is listed at all. I am testing my code on Firefox 56.0 (Ubuntu).
On searching over the internet, I did come across a StackOverflow answer that suggested that the getVoices() function should be called after the |onVoiceChanged| event
window.speechSynthesis.onvoiceschanged = function() {
window.speechSynthesis.getVoices();
...
};
I am invoking the call in the above mentioned manner and it works as desired in Chrome, but not on Firefox.
Another StackOverflow answer suggested that I enable the |media.webspeech.synth.enabled| in about:config of Firefox, but in my Firefox the preference |media.webspeech.synth.enabled| is already set to true.
I checked the MDN documentation https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis/getVoices and the example on this page does not run for me in Firefox, but runs fine in Chrome. I found that CanIUse.com lists that SpeechSynthesis as supported in Firefox 55 onwards, but it does not work for me.
Also The demo by Mozilla Developer Network to demonstrate the Speech Synthesis fails to work on my Firefox, but runs fine on Google Chrome. I have extensively searched online for a solution but could not find one. Can someone please point me in the right direction here.

Ran into the same issue and here's what I figured out.
Doesn't work for me on Firefox Ubuntu 16.04
On virtualbox Windows works. The voices come from Windows. "Microsoft David" is one of the choices.
Chrome works on Ubuntu, but only when it's online. It's not showing any traffic in the console, but the voice only works when it is online!

For anyone else still struggling with this, this is what fixed it for me. Assuming speech-dispatcher and espeak are already installed, the issue may be that there are multiple speech-dispatcher output modules installed and the default of them has no voices.
For example, on my system,
# spd-say -O lists output modules
$ spd-say -O
OUTPUT MODULES
espeak-ng-mbrola
espeak-ng
# spd-say -L lists all voices associated with the current
# output module
$ spd-say -L
NAME LANGUAGE VARIANT
$
Notice that spd-say -L outputs an empty table, even though spd-say "Hello world" works. I had no voices installed for the default speech-dispatcher module.
The second module in the list, espeak-ng, does have voices installed. Running spd-say -o espeak-ng -L produces a long table (-o selects a specific module).
Firefox seems to only query the default output module. This AskUbuntu post explains how to change the default output module.
Installing another output module, however, fixed the issue for me (I had trouble changing the default output module via /etc/speech-dispatcher/speechd.conf).
In short,
$ sudo apt install speech-dispatcher-pico
fixed the issue.

I'm running FireFox 58.0.2 (64-bit) under Windows 7 64 bit pro. The demo you mention does list one voice for me: Microsoft Anna - English (United States) (en-US). This voice is furnished by my Windows OS, not FireFox (Chrome lists 19 additional voices which are included with Chrome).
The reason your code works in Chrome but not Firefox is that Firefox doesn't invoke speechSynthesis.onvoiceschanged and Chrome does.
Why? Here is Mozilla's description of the voiceschanged event:
The voiceschanged event of the Web Speech API is fired when the list
of SpeechSynthesisVoice objects that would be returned by the
SpeechSynthesis.getVoices() method has changed (when the voiceschanged
event fires.)
Just a guess, but possibly the reason for the difference is that Chrome fires the event after it "adds" voices to your page. Firefox doesn't, so it doesn't.
The aforementioned demo gets around this incompatibility by calling populateVoiceList() right before the conditional code that triggers it (fourth line from bottom below, from here (CC0 licensed):
function populateVoiceList() {
voices = synth.getVoices();
var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if(voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
This is the approach I've adopted for my web application; otherwise my list of voices never gets populated by Firefox. This code also happens to address a similar problem with Safari; see voiceschanged event not fired in Safari.

The original bug seems to indicate you need speechd (speech-dispatcher) installed, see https://bugzilla.mozilla.org/show_bug.cgi?id=1003464.

I had similar issue and solve it by using setTimeout, this is probably not the perfect solution but it works for me, give it a try
window.speechSynthesis.onvoiceschanged = setTimeout(function() {
window.speechSynthesis.getVoices();
}, 1000);

Related

VS2015 error "Application is not currently attached to a script debug target that supports script diagnostics"

I created JS & HTML5 Blank App with Visual Studio 2015. When running it in VS debugger in "Local Machine" mode, I get the following error message:
Application is not currently attached to a script debug target that
supports script diagnostics
Just ignoring the error is not workable as at least breakpoints and console.log("text") do not work.
I'm having default options in VS.
I am running normal Win10, with automatic updates on.
Reinstallation of VS2015 did not solve the issue.
This worked for me although I was doing something slightly different. I got the same error message using IE 11 accessing a HTML file from my local file system (was mucking around with HTML). Seems IE developer tools don't much like this mode of operation (why?!). Here's my story...
File on my local windows laptop:
c:\temp\test.html
Can be opened in these browsers:
URL: file:///C:/Temp/test.html (in chrome)
URL: C:\Temp\test.html (in IE 11)
In Chrome tools commands in the console can be run no problem e.g.
console.log("hi");
In IE developer tools this fails with the message cited by the op.
I had a reverse proxy installed on my laptop (nginx) so tried serving the file up via HTTP and this fixed the issue with IE. Here's how I would access the file via HTTP via the proxy:
http://localhost:9092/temp/test.html
For reference here's my nginx.conf (but any other proxy would I expect work fine)...
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 9092;
server_name localhost;
location /temp {
alias "C:/temp/";
}
}
}
In my case (VS 2017 not 2015), the option shown below had somehow become unticked (I'm blaming an update). Before ticking this I was getting the same error as the OP; after ticking it, all is well again.
NB I'm debugging the Javascript within a WebBrowser control hosted in a Winform.
I finally got this solved with the help of Jack-Zhai in msdn forum. So, the summary of my journey:-
Problem:
- Running JS UWP blank app in debug mode & local machine w default settings in VS2015 generates a warning "Application is not currently attached to a script debug target that supports script diagnostics" into JavaScript console. Breakpoints do not work, adding console.log("here") does not write anything to console
Solution trial 1:
- changing and playing with VS2015 settings; the problem still exists
Solution trial 2:
- reinstalling VS2015; the problem still exists
Solution trial 3:
- reinstalling Windows10 - all applications deleted but user data not
- installing VS2015
=> Problem solved; debugging blank app works, and console.log("test") works

How can I disable signature checking for Firefox add-ons?

Since version 42, Firefox, by default, refuses to install unsigned add-ons. How do I disable this verification?
It is only possible to disable addons verification in Nightly and Developer channel. In other words it is not possible in Beta versions and standard releases.
Go to about:config (enter it into address bar)
Set xpinstall.signatures.required to false.
More at https://wiki.mozilla.org/Addons/Extension_Signing
Disable add-on signing check in Release (all) versions of Firefox
Firefox version 65+ (or so)
The following instructions will disable signature checking on Firefox for the Firefox profile in which you install the files. You are going to be adding some files to the chrome directory under your Firefox Profile directory.
This code will not work if javascript.enabled is set to False in about:config. That option needs to be set to True, which is the default setting.
As of Firefox 69+, it is expected that, in addition to the instructions below, you will need to have toolkit.legacyUserProfileCustomizations.stylesheets set to true in about:config. If it does not exist, then you will need to create it ("new" in the right-click context menu) as a Boolean option. See Bugzilla 1541233 for more detail about the addition of this option.
I've tested this on Firefox 66.0.3+.
The process of upgrading versions appears to briefly run the browser code with these changes not active. Thus, the first time you run a new version of Firefox any extensions you have installed that rely on disabling add-on signing will be disabled. You can immediately re-install those extensions after the upgrade to a new Firefox version and the extensions should resume working.
IIRC, some slightly different code was needed for Firefox 65, I believe I left that code in disable-add-on-signing.js when I modified it for Firefox 66, but I'm not sure about that.
We're going to use a technique which allows you to run arbitrary JavaScript code in the browser context from files stored in your Firefox profile directory. I found how to do this from Haggai Nuchi's GitHub repository: Firefox Quantum compatible userChrome.js.
On Windows, your Firefox profile directory will be %appdata%\Mozilla\Firefox\Profiles\[profileID]. If you have only one profile, the [profileID] will be the only directory in the %appdata%\Mozilla\Firefox\Profiles directory. If you have multiple profiles, you will need to select the one(s) you want to install this hack into.
Once you get to your profile directory, your will need to create a directory called chrome, if it does not already exist. You will be adding the 3 files below to that directory:
userChrome.css
userChrome.xml
disable-add-on-signing.js
You will then need the following code in userChrome.css, which is available from Haggai Nuchi's GitHub repository:
/*Enable userChrome.js */
/* Copyright (c) 2017 Haggai Nuchi
Available for use under the MIT License:
https://opensource.org/licenses/MIT
*/
#namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
toolbarbutton#alltabs-button {
-moz-binding: url("userChrome.xml#js");
}
You will need userChrome.xml (slightly modified from the version available in Haggai Nuchi's GitHub repository):
<?xml version="1.0"?>
<!-- Copyright (c) 2017 Haggai Nuchi
Available for use under the MIT License:
https://opensource.org/licenses/MIT
-->
<!-- This has been slightly modified from the version available from
https://github.com/nuchi/firefox-quantum-userchromejs/blob/master/userChrome.xml
by Makyen. The modified version is released under both the MIT and CC BY-SA 3.0 licenses.
-->
<bindings id="generalBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="js" extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged">
<implementation>
<constructor><![CDATA[
function makeRelativePathURI(name) {
let absolutePath = Components.stack.filename;
return absolutePath.substring(0, absolutePath.lastIndexOf("/") + 1) + name;
}
// The following code executes in the browser context,
// i.e. chrome://browser/content/browser.xul
try {
Services.scriptloader.loadSubScript(makeRelativePathURI("disable-add-on-signing.js"), window);
} catch(e) {
console.error(e);
}
]]></constructor>
</implementation>
</binding>
</bindings>
You will also need disable-add-on-signing.js:
//This should be installed as the file disable-add-on-signing.js in
// your profile's "chrome" directory.
//Earlier versions of Firefox
try {
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {}).eval("SIGNED_TYPES.clear()");
} catch(ex) {}
try {
Components.utils.import("resource://gre/modules/addons/XPIInstall.jsm", {}).eval("SIGNED_TYPES.clear()");
} catch(ex) {}
try {
Components.utils.import("resource://gre/modules/addons/XPIDatabase.jsm", {}).eval("SIGNED_TYPES.clear()");
} catch(ex) {}
//Tested on Firefox 66
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
XPIDatabase: "resource://gre/modules/addons/XPIDatabase.jsm",
});
XPIDatabase.SIGNED_TYPES.clear();
console.log('Add-on signing disabled.');
After adding these files in your profile's chrome directory, you will need to restart Firefox. You can verify that the code is running by looking for "Add-on signing disabled." in the Browser Console.
Add-ons which were disabled or removed by Firefox will not be automatically enabled. You will need to re-install them. You can install them by draging-and-droping the *.xpi file onto a Firefox window and confirming that you want to install.
If you are wanting to get the *.xpi file for any particular extension from Mozilla Add-ons you can download it by right clicking on the "install" button and selecting "Save As", or "Remove".
Firefox version 57 or earlier (or so)
Unfortunately, I don't recall with which version of Firefox this this method stopped working. I know I was using it on Firefox 54, 55, 52ESR and FF56.*.
I initially found this solution for disabling forced add-on signature checking in this blog post, which is the original source for the (somewhat modified) code in this answer. Making these changes will allow you to install unsigned add-ons into profiles using the Firefox distribution you modify. For most people, this will be your main Firefox installation. However, if you have installed multiple versions, you will need to make this modification in each installation. However, once you make the modifications, they will remain through normal Firefox updates.
You will need to add a couple of files within the Firefox installation directory. You can find a list of installation directory examples for Windows, Linux, and Mac OS on mozillaZine. The most common install directories are:
Windows
C:\Program Files\Mozilla Firefox\
C:\Program Files (x86)\Mozilla Firefox\
Linux
/usr/lib/firefox-<version>
OSX
/Applications/Firefox.app
Add first file
You then need to add code below as the file <Install directory>/defaults/pref/disable-add-on-signing-prefs.js (Windows: <Install directory>\defaults\pref\disable-add-on-signing-prefs.js):
//This file should be placed in the defaults/pref directory (folder)
//within the Firefox installation directory with the with the name:
// disable-add-on-signing-prefs.js
pref("general.config.obscure_value", 0);
pref("general.config.filename", "disable-add-on-signing.js");
Add second file
You also need to add the code below as the file <Install directory>/disable-add-on-signing.js (Windows: <Install directory>\disable-add-on-signing.js):1
//This file should be placed in the Firefox installation directory
//(folder) with the with the name:
// disable-add-on-signing.js
try {
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
.eval("SIGNED_TYPES.clear()");
} catch(ex) {}
try {
Components.utils.import("resource://gre/modules/addons/XPIInstall.jsm", {})
.eval("SIGNED_TYPES.clear()");
} catch(ex) {}
Results
I've been using these solutions for years now to have a few extensions I built for my own use installed and to test new versions of extensions I'm working on (when I want to test in the Release version instead of Firefox Developer Edition or Nightly).
NOTE: In about:addons Firefox may show (under some conditions) the add-on as enabled (not greyed-out), but have text stating that the add-on "could not be verified and has been disabled". The text is not accurate! The add-on is enabled and functioning.
How it works
Within resource://gre/modules/addons/XPIProvider.jsm the const SIGNED_TYPES is defined as a Set. In order for an add-on to require signing, its type must be a member of that Set. The Set.prototype.clear() method is used to clear all entries from the Set. This results in no add-on types which require signing (code 1, code 2).
If you wanted to, you could individually disable the signature check for any of the types: "webextension", "extension", "experiment", or "apiextension".
Remove the META-INF directory from any modified extension
The additional files in the sections above turn off the requirement that extensions must be signed. If the signature files exist, the signature will still be verified. Thus, if you have modified an extension from one that was singed and have not removed the signature files, the extension will fail signature verification. In other words, actually checking any existing signatures is a separate step from the requirement that the signature must exist.
If you have modified an extension which had been signed (you can tell that it had been signed by the existence of a META-INF directory in the extension's root directory), then you will need to remove the signature files. You can do this by removing the META-INF directory and all files contained in that directory.
1. The code in the blog puts this call in a try{}catch(){} block. There's really no need to do so. The only effective thing that doing so does is prevent any error from being reported in the Browser Console (Ctrl-Shift-J, or Cmd-Shift-J on OSX). There's no additional code that is desired to be run if this fails. In addition, I would prefer to be able to see the error in the Browser Console if this fails in order to know that it has, in fact, failed. Not having the try{}catch(){} doesn't have any negative effects and permits tracking down the problem if, on some future version of Firefox, add-ons start being disabled because of not being signed.
To complete the above answer, i discover firefox-autoconfig, that consists of installing an autoconfig.js file in <FIREFOX INSTALLATION DIR>/default/prefs and a ci.clg file in <FIREFOX INSTALLATION DIR> that's a way to disable xpinstall.signatures.required (and other options too) definitively and automatically when Firefox is opened (tested with Firefox 45.0.1)
You will see those contents in autoconfig.js:
//
pref("general.config.filename", "ci.cfg");
pref("general.config.obscure_value", 0);
And those contents in ci.cfg:
// Disable checking if firefox is default browser
lockPref('browser.shell.checkDefaultBrowser', false);
// Disable restoring session
lockPref('browser.sessionstore.resume_from_crash', false);
// Disable extension signature check
lockPref('xpinstall.signatures.required', false);
// Allow extensions to be installed without user prompt
pref("extensions.autoDisableScopes", 0);
pref("extensions.enabledScopes", 15);
// Disable updater
lockPref("app.update.enabled", false);
// make absolutely sure it is really off
lockPref("app.update.auto", false);
lockPref("app.update.mode", 0);
lockPref("app.update.service.enabled", false);
// Prevent closing dialogs
lockPref("browser.showQuitWarning", false);
lockPref("browser.warnOnQuit", false);
lockPref("browser.tabs.warnOnClose", false);
lockPref("browser.tabs.warnOnCloseOtherTabs", false);
// Disable Add-ons compatibility checking
clearPref("extensions.lastAppVersion");
// Don't show 'know your rights' on first run
pref("browser.rights.3.shown", true);
//Disable plugin checking
lockPref("plugins.hide_infobar_for_outdated_plugin", true);
clearPref("plugins.update.url");
// Disable health reporter
lockPref("datareporting.healthreport.service.enabled", false);
// Disable all data upload (Telemetry and FHR)
lockPref("datareporting.policy.dataSubmissionEnabled", false);
// Disable crash reporter
lockPref("toolkit.crashreporter.enabled", false);
Components.classes["#mozilla.org/toolkit/crash-reporter;1"].getService(Components.interfaces.nsICrashReporter).submitReports = false;
// Browser Console command line
pref("devtools.chrome.enabled", true);
As of Firefox 47: release and Beta versions of Firefox for Desktop will not allow unsigned extensions to be installed, with no override.
For more info see the Mozilla Wiki page on Extension Signing.
#Makyen's solution works but will disable signature checking completely:
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
.eval("SIGNED_TYPES.clear()");
You will not have the information of whether the addon is signed.
Instead I'd suggest this:
/* Let unsigned addons live! */
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
.eval("function mustSign(aType) { return false; }");
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
.eval("XPIProvider.verifySignatures = function() {}");
It will still warn you when you try to install an unsigned addon but it will work anyway. The addon is flagged as disabled in about:addons but is in fact active (you can disable/enable it manually like a normal addon).
How it works:
mustSign() checks whether signature is required for this type of addon.
verifySignatures() is a callback used to check signatures every XPI_SIGNATURE_CHECK_PERIOD seconds (i.e. once per day)
This is the code which I found in the thread on HackerNews regarding add-on signing apocalypse. It works in Firefox 56 and older versions without restarting.
// For FF < v57 >...?
async function set_addons_as_signed() {
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
let XPIDatabase = this.XPIInternal.XPIDatabase;
let addons = await XPIDatabase.getAddonList(a => true);
for (let addon of addons) {
// The add-on might have vanished, we'll catch that on the next startup
if (!addon._sourceBundle.exists())
continue;
if( addon.signedState != AddonManager.SIGNEDSTATE_UNKNOWN )
continue;
addon.signedState = AddonManager.SIGNEDSTATE_NOT_REQUIRED;
AddonManagerPrivate.callAddonListeners("onPropertyChanged",
addon.wrapper,
["signedState"]);
await XPIProvider.updateAddonDisabledState(addon);
}
XPIDatabase.saveChanges();
}
set_addons_as_signed();
This code needs to be executed in the browser console (not web console) which can be accessed via the shortcut Ctrl+Shift+J. It instantly reenables all addons which failed verification.
A simpler approach I discovered that seems to work is flipping the constant that Firefox uses to determine whether to enforce signing. This will likely need to be done after each Firefox update.
Locate the omni.ja archive in your Firefox install directory
Extract this file as a zip archive to a working folder
Edit modules/AppConstants.jsm in your text editor, and change the value under MOZ_REQUIRE_SIGNING from false to true
Re-zip the modified contents back into omni.ja
Verify that xpinstall.signatures.required and xpinstall.whitelist.required are false under about:config, and restart firefox
Your unsigned addons should now install.

crash dumps missing nodewebkit

I'm developing an application (on Windows now but I'd like to have a mac version as well) using angularjs and node webkit.
It happens that my application crashes but I don't know why. So I thought I should check the dump file generated as precised here : https://github.com/rogerwang/node-webkit/wiki/Crash-dump
So here is my code :
// Load native UI library
var ngui = require('nw.gui');
ngui.App.setCrashDumpDir("logs");
// Get the current window
var nwin = ngui.Window.get();
// show devtools to debug
nwin.showDevTools();
onload = function() {
nwin.show();
nwin.maximize();
}
ngui.App.crashBrowser();
I've put the last line to find a crash report but I'm unable to find any in the logs folder of my application.
Why ?
Thank you
I did some digging in the source and found the reason. It appears that setCrashDumpDir has been disabled in 0.12 for whatever reason.
In breakpad_win.cc, SetSetCrashDumpPath should have been called from app.cc (nw.app module).
The commit responsible for this was authored by GnorTech and has been disabled since Aug. 29th, 2014.
I'm going to raise a bug report for this.
EDIT:
Looks like a bug report already exists. https://github.com/nwjs/nw.js/issues/3226

JavaScript: "Uncaught SecurityError" when running JS-XSL demo locally

(This question pertains to the JS-XSL demo found here)
To briefly tell you what this demo is for; it takes a MS Excel file as input, parses the data, and outputs the data in text-only format. I downloaded the package (zip) and ran it locally, simply by opening the html file with Chrome.
The problem is, I just cannot seem to get over the following error:
Uncaught SecurityError: Failed to construct 'Worker': Script at 'file:///C:/Users/David/Desktop/Xlsx%20Demo/xlsworker.js' cannot be accessed from origin 'null'.
And above error points to line 34 of the html file, which has the following code:
/* I changed the file path from './xlsworker.js' to 'xlsworker.js' */
var worker = new Worker('xlsworker.js');
There are only three files for this demo: the html file itself, and two javascript files, one is named xls.js and the other xlsworker.js. All three files are in the same directory and at the same level.
What's rather baffling to me is, I successfully ran this same demo about a couple months ago! I cannot imagine if I am doing anything differently now. Any insight?
https://code.google.com/p/chromium/issues/detail?id=278883#c9
You are basically prevented by Chromium to use workers on the file:// protocol, you have to host your files and access them through the http:// protocol.
You need a server (even something simple like http://docs.python.org/2/library/simplehttpserver.html)
IMO, the below is a superior answer, because it does not require running a web-server. It's extremely quick and simple.
(the downvote is explained in my Note 5, below)
I have tested and verified that this solution works with the demo linked by the asker, when run locally as described by the asker. Tested on Windows 10, Chrome Stable x64 48.0.2564.103 m.
A script is not allowed to access to your local file system in Chrome. If you'd like to test web workers locally, you have to open Chrome with a special flag.
On Windows, launch chrome with the flag:
chrome.exe --allow-file-access-from-files
After that Chrome will be launched and you can test workers during this session.
Note1: if Chrome is already running when you run this command, the new instance of Chrome will not allow Workers to run-- you must first exit from Chrome (if necessary, use Windows Task Manager to ensure Chrome is not running).
Note 2: the source for this answer (link below) includes the --args flag on Windows, but i have not found the "args" to be necessary on Windows. In fact, i cannot find any documentation of the "args" flag anywhere-- not sure what it does. So i don't include it in the Windows command, above.*
Note 3: For those trying to do something similar on Chrome-Mac, or Windows-Firefox, the link below includes both, along with the Windows-Chrome solution above. But my solution described above is only the Windows-Chrome method.
http://js-workout.tompascall.com/web-workers-and-responsiveness/
Note 4: Be aware that this solution is not the same as running a web-server, but for your purpose it should be a completely adequate solution. Also, be aware that to browse the web with this chrome startup-switch enabled may compromise your local file-security, so it's advised to only use this method for your local file purpose, and disable it for web-browsing.*
Note 5: Google states that using startup flags "should only be used for temporary cases and may break in the future." Web search for chrome startup switches returns about 2,000 hits, so lots of people use them and blog about them. If your need is temporary, then this currently works great.*

pdf.js not working with Safari

We're testing out pdf.js and while it seems like an awesome project we can't get it working in Safari.
(Tested on PDF.JS version = 0.8.229 (latest) / Safari 5.1.9 - 6.0.4 / Mac OSX 10.6.8 - 10.8.3)
EXAMPLE:
This is an example of the demo code served from our server with a sample PDF that works on Chrome/FFox but not Safari:
http://test.appgrinders.com/pdf_js/test.html
Console output:
Warning: Setting up fake worker.
Error: Invalid XRef stream (while reading XRef):
Error: Invalid XRef stream pdf.js:850undefined
Warning: Indexing all PDF objects
Error: Invalid XRef stream (while reading XRef):
Error: Invalid XRef stream pdf.js:850undefined
More tests:
The following is a list of sample PDFs we tested (They were all served from our server, and all worked in Chrome/FFox/Android). The only one that worked with Safari was the PDF file served from the pdf.js project itself:
FAILS IN SAFARI:
http://samplepdf.com/sample.pdf
http://forums.adobe.com/servlet/JiveServlet/previewBody/2041-102-1-2139/Sample.pdf
https://github.com/prawnpdf/prawn/raw/master/data/pdfs/form.pdf
WORKS IN SAFARI:
http://cdn.mozilla.net/pdfjs/helloworld.pdf
(NOTE: This is a sample PDF from the pdf.js project and the only one we ever got working)
We've submitted a bug report, but the developers do not seem to have an answer, so I'm hoping someone here might...
How can we get pdf.js working with Safari?
I've figured out how to get things working on Mac Safari (without necessarily understanding why)...
compatibility.js must be included.
PDFJS.workerSrc must be assigned.
The demo code I had been testing (from the JS Bin demos here)
does not do this, though some other online examples do (including
the hello world example and the examples provided by
#AndrewBenjamin – thanks). Other browsers don't seem to require this,
but Safari won't work without it.
<script type="text/javascript" src="compatibility.js"></script>
<script type="text/javascript" src="pdf.js"></script>
<!-- NEED THIS for Safari Mac to render work -->
<script type="text/javascript">
// Specify the main script used to create a new PDF.JS web worker.
// In production, change this to point to the combined `pdf.js` file.
PDFJS.workerSrc = 'pdf.worker.js';
</script>
Again, can't explain why, but this is how we got it working for us.
I've got PDF.js working fine in Safari on my local server, but when I put it on the remote server, the goofy error comes back:
Warning: Setting up fake worker.
Unhandled rejection: Error: INVALID_STATE_ERR: DOM Exception 11
It will also show this error on my local computer if I happen to have the developer console open. Close the console, PDF displays in Safari; open the console, and it doesn't work anymore.
The question is: what do the developer tools and the remote server change versus running on a local server? Is this still a range-checking problem?
I got PDF.js to work, though! I've modified so much stuff I don't know what part of what I did worked. Here's a list of stuff I did.
Added compatibility.js – modified the last function in it to read like this:
(function checkRangeRequests() {
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
if (!isSafari) {
return;
}
document.addEventListener('DOMContentLoaded', function (e) {
if (isSafari) {
PDFJS.disableRange = true;
}
});
})();
Changed the order of xhr.open() calls in pdf.js so that xhr.setRequestHeader() occurs after xhr.open()
Removed all 'use strict'; lines
Added xhr.setRequestHeader("Cache-control", "no-cache"); after xhr.open on lines 37272 and 41262
Minified pdf.js and it all works all the time!
PDFJS.getDocument() will accept either a string link or a Uint8Array. In my client side version I pass PDFJS.getDocument() a Uint8Array, but if I want an existing file rendered, I just pass the path to the file:
jspdf line 965:
PDFJS.getDocument('..files/pdf/sample.pdf').then(function(pdf) {
I don't know what makes your safari browser fail, but if you can see sample.pdf on my test site, you have to be very close to solving this.
I've figured out how to get things working on Mac Safari & iPad
I removed the 'strict mode' at the beginning of
1. pdf.js/src/core/worker.js
2. pdf.js/web/download_manager.js
And worked!!
if you're going to support versions below Safari 14, from what I understood PDFjs doesn't support that.
you will need to use an external viewer in an object tag:
<object data="https://drive.google.com/viewerng/viewer?embedded=true&url=https://researchtorevenue.files.wordpress.com/2015/04/1r41ai10801601_fong.pdf&embedded=true"></object>
I had the same problem with Safari Mobile... Can't open more than 1 Mb PDF's... I solved fragmenting the file in parts of 900 kb, join them in local and then injecting to pdf.js as Uint8Array() object. I think it's a no documented limitation.

Categories

Resources