Re-hack Windows send-url around the IE7 bug
svn: r8456
original commit: 09ec3eddbd
This commit is contained in:
parent
9b4f372c3a
commit
abdb9918fe
|
@ -34,12 +34,14 @@
|
||||||
x
|
x
|
||||||
(error 'external-browser "~e is not a valid browser preference" x)))))
|
(error 'external-browser "~e is not a valid browser preference" x)))))
|
||||||
|
|
||||||
|
(define (find-exe name)
|
||||||
|
(find-executable-path name #f))
|
||||||
|
|
||||||
;; by-need filtering of found unix executables
|
;; by-need filtering of found unix executables
|
||||||
(define existing-unix-browsers->exes
|
(define existing-unix-browsers->exes
|
||||||
(delay
|
(delay
|
||||||
(filter values
|
(filter values (map (lambda (b)
|
||||||
(map (lambda (b)
|
(let ([exe (find-exe (symbol->string b))])
|
||||||
(let ([exe (find-executable-path (symbol->string b) #f)])
|
|
||||||
(and exe (cons b exe))))
|
(and exe (cons b exe))))
|
||||||
all-unix-browsers))))
|
all-unix-browsers))))
|
||||||
(define existing-unix-browsers
|
(define existing-unix-browsers
|
||||||
|
@ -86,31 +88,11 @@
|
||||||
"don't know how to open URL on platform: ~s" stype)])))
|
"don't know how to open URL on platform: ~s" stype)])))
|
||||||
(void))
|
(void))
|
||||||
|
|
||||||
(define osascript (delay (find-executable-path "osascript" #f)))
|
(define osascript (delay (find-exe "osascript")))
|
||||||
(define (send-url/mac url-str)
|
(define (send-url/mac url)
|
||||||
(browser-run (force osascript) "-e" (format "open location \"~a\"" url-str)))
|
(browser-run (force osascript) "-e" (format "open location \"~a\"" url)))
|
||||||
|
|
||||||
(define (send-url/win url-str)
|
(define (send-url/unix url separate-window?)
|
||||||
(define (simple)
|
|
||||||
(shell-execute #f url-str "" (current-directory) 'SW_SHOWNORMAL))
|
|
||||||
(if (regexp-match #rx"#" url-str)
|
|
||||||
;; complex case: need to launch the browser directly,
|
|
||||||
;; otherwise the fragment is ignored. Use `ftype' to discover
|
|
||||||
;; the browser...
|
|
||||||
(let ([p (process "ftype htmlfile")])
|
|
||||||
(close-output-port (cadr p))
|
|
||||||
(let ([s (read-line (car p) 'return-linefeed)])
|
|
||||||
(close-input-port (car p))
|
|
||||||
(close-input-port (cadddr p))
|
|
||||||
(let ([m (regexp-match #rx"^htmlfile=(.*)" s)])
|
|
||||||
(if m
|
|
||||||
(browser-run #:shell #t (string-append (cadr m) " " url-str))
|
|
||||||
;; give up and use simple mode
|
|
||||||
(simple)))))
|
|
||||||
;; simple case: no fragment
|
|
||||||
(simple)))
|
|
||||||
|
|
||||||
(define (send-url/unix url-str separate-window?)
|
|
||||||
;; in cases where a browser was uninstalled, we might get a preference that
|
;; in cases where a browser was uninstalled, we might get a preference that
|
||||||
;; is no longer valid, this will turn it back to #f
|
;; is no longer valid, this will turn it back to #f
|
||||||
(define (try pref)
|
(define (try pref)
|
||||||
|
@ -125,21 +107,17 @@
|
||||||
(define exe
|
(define exe
|
||||||
(cond [(assq browser (force existing-unix-browsers->exes)) => cdr]
|
(cond [(assq browser (force existing-unix-browsers->exes)) => cdr]
|
||||||
[else #f]))
|
[else #f]))
|
||||||
(define (simple) (browser-run exe url-str))
|
(define (simple) (browser-run exe url))
|
||||||
(define (w/arg a) (browser-run exe a url-str))
|
(define (w/arg a) (browser-run exe a url))
|
||||||
(define (try-remote)
|
(define (try-remote)
|
||||||
(or (system* exe "-remote"
|
(or (system* exe "-remote" (format "openURL(~a~a)" url
|
||||||
(format "openURL(~a)"
|
(if separate-window? ",new-window" "")))
|
||||||
(if separate-window?
|
|
||||||
(format "~a,new-window" url-str)
|
|
||||||
url-str)))
|
|
||||||
(simple)))
|
(simple)))
|
||||||
(cond
|
(cond
|
||||||
[(not browser)
|
[(not browser)
|
||||||
(error 'send-url "Couldn't find a browser to open URL: ~e" url-str)]
|
(error 'send-url "Couldn't find a browser to open URL: ~e" url)]
|
||||||
[(custom-browser? browser)
|
[(custom-browser? browser)
|
||||||
(browser-run #:shell #t
|
(browser-run #:shell #t (string-append (car browser) url (cdr browser)))]
|
||||||
(string-append (car browser) url-str (cdr browser)))]
|
|
||||||
;; if it's a known browser, then it must be an existing one at this point
|
;; if it's a known browser, then it must be an existing one at this point
|
||||||
[(not exe) (error 'send-url "internal error")]
|
[(not exe) (error 'send-url "internal error")]
|
||||||
;; if it's gone throw an error (refiltering will break assumptions of
|
;; if it's gone throw an error (refiltering will break assumptions of
|
||||||
|
@ -160,18 +138,65 @@
|
||||||
;; opera starts a new browser automatically
|
;; opera starts a new browser automatically
|
||||||
(browser-run exe "-remote"
|
(browser-run exe "-remote"
|
||||||
(format "openURL(~a~a)"
|
(format "openURL(~a~a)"
|
||||||
url-str (if separate-window? ",new-window" "")))]
|
url (if separate-window? ",new-window" "")))]
|
||||||
[else (error 'send-url "internal error")])]))
|
[else (error 'send-url "internal error")])]))
|
||||||
|
|
||||||
|
;; Windows -- IE7 has a bug: when launched (either through shell-execute or
|
||||||
|
;; directly) it will ignore the fragment for `file:' URLs. A workaround that
|
||||||
|
;; seems to work is to run `explorer.exe' instead. The problem is described at
|
||||||
|
;; http://support.microsoft.com/default.aspx/kb/942172, and when a fix will be
|
||||||
|
;; released (and enough time to be widely used), this whole thing should go
|
||||||
|
;; away and the simple `shell-eexcute' will work fine. (See also
|
||||||
|
;; http://www.tutorials-win.com/IE/Lauching-HTML/)
|
||||||
|
|
||||||
|
(define (using-ie7?)
|
||||||
|
(define (bytes0 bs)
|
||||||
|
(list->bytes (apply append (map (lambda (b) (list b 0)) (bytes->list bs)))))
|
||||||
|
(define (get-regdata)
|
||||||
|
(define regfile (make-temporary-file "registry-data-~a"))
|
||||||
|
(and (system (format "regedit /e \"~a\" \"~a" regfile
|
||||||
|
(regexp-replace* #rx"/" keypath "\\\\")))
|
||||||
|
(let ([x (file-size regfile)])
|
||||||
|
(begin0 (with-input-from-file regfile (lambda () (read-bytes x)))
|
||||||
|
(delete-file regfile)))))
|
||||||
|
(define keypath
|
||||||
|
"HKEY_LOCAL_MACHINE/Software/Microsoft/Internet Explorer/Version Vector")
|
||||||
|
(define version-rx
|
||||||
|
(bytes-append (bytes0 #"\r\n\"IE\"=\"") #"([0-9.\0]+)" (bytes0 #"\"\r\n")))
|
||||||
|
(and
|
||||||
|
;; Is IE the default browser?
|
||||||
|
(let ([p (process "ftype http")])
|
||||||
|
(close-output-port (cadr p))
|
||||||
|
(let ([s (read-line (car p) 'return-linefeed)])
|
||||||
|
(close-input-port (car p))
|
||||||
|
(close-input-port (cadddr p))
|
||||||
|
(regexp-match? #px"^(?i:http=\"(.*\\\\|)iexplore.exe\")" s)))
|
||||||
|
;; Get the registry data and check the version. We could convert the UTF-16
|
||||||
|
;; result to UTF-8, but we're looking for a simple pattern, so just search
|
||||||
|
;; for the expected UTF-16 sequence directly.
|
||||||
|
(cond [(regexp-match version-rx (get-regdata))
|
||||||
|
=> (lambda (m) (regexp-match? #rx#"^7\0\\.\0" (cadr m)))]
|
||||||
|
[else #f])))
|
||||||
|
|
||||||
|
(define send-url/win-proc
|
||||||
|
(delay (let ([explorer (and (using-ie7?) (find-exe "explorer.exe"))])
|
||||||
|
(if explorer
|
||||||
|
(lambda (url) (browser-run #:ignore-exit-code #t explorer url))
|
||||||
|
(lambda (url)
|
||||||
|
(shell-execute #f url "" (current-directory) 'SW_SHOWNORMAL))))))
|
||||||
|
|
||||||
|
(define (send-url/win url) ((force send-url/win-proc) url))
|
||||||
|
|
||||||
;; Process helper
|
;; Process helper
|
||||||
(define (browser-run #:shell? [shell? #f] . args)
|
(define (browser-run #:shell [shell? #f] #:ignore-exit-code [nowait? #f] . args)
|
||||||
(define-values (stdout stdin pid stderr control)
|
(define-values (stdout stdin pid stderr control)
|
||||||
(apply values (apply (if shell? process/ports process*/ports)
|
(apply values (apply (if shell? process/ports process*/ports)
|
||||||
(open-output-nowhere) #f (current-error-port)
|
(open-output-nowhere) #f (current-error-port)
|
||||||
args)))
|
args)))
|
||||||
(close-output-port stdin)
|
(close-output-port stdin)
|
||||||
|
(unless nowait?
|
||||||
(thread (lambda ()
|
(thread (lambda ()
|
||||||
(control 'wait)
|
(control 'wait)
|
||||||
(when (eq? 'done-error (control 'status))
|
(when (eq? 'done-error (control 'status))
|
||||||
(error 'browser-run "process execute failed: ~e" args))))
|
(error 'browser-run "process execute failed: ~e" args)))))
|
||||||
(void))
|
(void))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user