Skip to content

Commit

Permalink
Merge pull request #7854 from rolandwalker/accessibility_stanza
Browse files Browse the repository at this point in the history
DSL: add `accessibility_access` stanza
  • Loading branch information
rolandwalker committed Dec 9, 2014
2 parents b2aad95 + 82826b2 commit 5036750
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ before_script:
# path-quoting is different here due to YAML constraints
# @@@ todo: setting the --seed here is an ugly temporary hack, to remain only until test-suite glitches are fixed.
script:
- /System/Library/Frameworks/Ruby.framework/Versions/"${CASK_RUBY_TEST_VERSION}"/usr/bin/bundle exec "/System/Library/Frameworks/Ruby.framework/Versions/${CASK_RUBY_TEST_VERSION}/usr/bin/rake" test TESTOPTS="--seed=14828"
- /System/Library/Frameworks/Ruby.framework/Versions/"${CASK_RUBY_TEST_VERSION}"/usr/bin/bundle exec "/System/Library/Frameworks/Ruby.framework/Versions/${CASK_RUBY_TEST_VERSION}/usr/bin/rake" test TESTOPTS="--seed=14829"

notifications:
irc:
Expand Down
1 change: 1 addition & 0 deletions doc/CASK_LANGUAGE_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Each Cask must declare one or more *artifacts* (i.e. something to install)
| `postflight` | yes | a Ruby block containing postflight install operations
| `uninstall_preflight` | yes | a Ruby block containing preflight uninstall operations (needed only in very rare cases)
| `uninstall_postflight` | yes | a Ruby block containing postflight uninstall operations
| `accessibility_access` | no | `true` if the application should be granted accessibility access
| `container :nested =>` | no | relative path to an inner container that must be extracted before moving on with the installation; this allows us to support dmg inside tar, zip inside dmg, etc.
| `container :type =>` | no | a symbol to override container-type autodetect. may be one of: `:air`, `:bz2`, `:cab`, `:dmg`, `:generic_unar`, `:gzip`, `:otf`, `:pkg`, `:rar`, `:seven_zip`, `:sit`, `:tar`, `:ttf`, `:xar`, `:zip`, `:naked`. (example [parse.rb](../Casks/parse.rb))
| `tags` | no | a list of key-value pairs for Cask annotation. Not free-form. (see also [Tags Stanza Details](#tags-stanza-details))
Expand Down
40 changes: 20 additions & 20 deletions doc/cask_language_deltas.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,26 @@ features which are available for the current Cask.

## Renamed Forms (1.0)

| old form | new form
| ------------------------------------- |----------------
| `after_install` | [`postflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `after_uninstall` | [`uninstall_postflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `arch_only` (within `caveats`) | [`depends_on :arch`](CASK_LANGUAGE_REFERENCE.md#depends_on-arch)
| `before_install` | [`preflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `before_uninstall` | [`uninstall_preflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `container_type` | [`container :type`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `depends_on_formula` | [`depends_on :formula`](CASK_LANGUAGE_REFERENCE.md#depends_on-formula)
| `destination_path` | [`staged_path`](CASK_LANGUAGE_REFERENCE.md#caveats-as-a-string)
| `install` | [`pkg`](CASK_LANGUAGE_REFERENCE.md#pkg-stanza-details)
| `link` | [`app`](CASK_LANGUAGE_REFERENCE.md#app-stanza-details) (or sometimes `suite` or `artifact`)
| `manual_installer` (within `caveats`) | [`installer :manual`](CASK_LANGUAGE_REFERENCE.md#installer-manual)
| `nested_container` | [`container :nested =>`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `os_version_only` (within `caveats`) | [`depends_on :macos`](CASK_LANGUAGE_REFERENCE.md#depends_on-macos)
| `title` (in interpolations) | [`token`](CASK_LANGUAGE_REFERENCE.md#caveats-as-a-string)
| `uninstall :files` | [`uninstall :delete`](CASK_LANGUAGE_REFERENCE.md#uninstall-key-delete)
| `version 'latest'` | [`version :latest`](CASK_LANGUAGE_REFERENCE.md#required-stanzas)
| `x11_required` (within `caveats`) | [`depends_on :x11`](CASK_LANGUAGE_REFERENCE.md#all-depends_on-keys)
| old form | new form
| --------------------------------------- |----------------
| `after_install` | [`postflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `after_uninstall` | [`uninstall_postflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `arch_only` (within `caveats`) | [`depends_on :arch`](CASK_LANGUAGE_REFERENCE.md#depends_on-arch)
| `assistive_devices` (within `caveats`) | [`accessibility_access`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `before_install` | [`preflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `before_uninstall` | [`uninstall_preflight`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `container_type` | [`container :type`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `depends_on_formula` | [`depends_on :formula`](CASK_LANGUAGE_REFERENCE.md#depends_on-formula)
| `destination_path` | [`staged_path`](CASK_LANGUAGE_REFERENCE.md#caveats-as-a-string)
| `install` | [`pkg`](CASK_LANGUAGE_REFERENCE.md#pkg-stanza-details)
| `link` | [`app`](CASK_LANGUAGE_REFERENCE.md#app-stanza-details) (or sometimes `suite` or `artifact`)
| `manual_installer` (within `caveats`) | [`installer :manual`](CASK_LANGUAGE_REFERENCE.md#installer-manual)
| `nested_container` | [`container :nested =>`](CASK_LANGUAGE_REFERENCE.md#optional-stanzas)
| `os_version_only` (within `caveats`) | [`depends_on :macos`](CASK_LANGUAGE_REFERENCE.md#depends_on-macos)
| `title` (in interpolations) | [`token`](CASK_LANGUAGE_REFERENCE.md#caveats-as-a-string)
| `uninstall :files` | [`uninstall :delete`](CASK_LANGUAGE_REFERENCE.md#uninstall-key-delete)
| `version 'latest'` | [`version :latest`](CASK_LANGUAGE_REFERENCE.md#required-stanzas)
| `x11_required` (within `caveats`) | [`depends_on :x11`](CASK_LANGUAGE_REFERENCE.md#all-depends_on-keys)


## All Supported Stanzas (1.0)
Expand Down Expand Up @@ -143,7 +144,6 @@ For use in *eg* interpolation:

## Caveats Mini-DSL (1.0)

* [`assistive_devices`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl)
* [`files_in_usr_local`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl)
* [`logout`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl)
* [`path_environment_variable(path)`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl)
Expand Down
9 changes: 9 additions & 0 deletions lib/cask/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def artifacts; self.class.artifacts; end

def caveats; self.class.caveats; end

def accessibility_access; self.class.accessibility_access; end

module ClassMethods

# A quite fragile shim to allow "full_name" be exposed as simply "name"
Expand Down Expand Up @@ -205,6 +207,13 @@ def caveats(*string, &block)
end
end

def accessibility_access(accessibility_access=nil)
if @accessibility_access and !accessibility_access.nil?
raise CaskInvalidError.new(self.token, "'accessibility_access' stanza may only appear once")
end
@accessibility_access ||= accessibility_access
end

def self.ordinary_artifact_types
@@ordinary_artifact_types ||= [
:app,
Expand Down
15 changes: 0 additions & 15 deletions lib/cask/dsl/postflight.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,6 @@ def suppress_move_to_applications(options = {})
@command.run!('/usr/bin/defaults', :args => ['write', bundle_identifier, key, '-bool', 'true'])
end

def enable_accessibility_access
if MacOS.version >= :mavericks
@command.run!('/usr/bin/sqlite3',
:args => [
Cask.tcc_db,
"INSERT INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);",
],
:sudo => true)
else
@command.run!('/usr/bin/touch',
:args => [Cask.pre_mavericks_accessibility_dotfile],
:sudo => true)
end
end

def method_missing(method, *args)
Cask::Utils.method_missing_message(method, @cask.to_s, 'postflight')
return nil
Expand Down
16 changes: 0 additions & 16 deletions lib/cask/dsl/uninstall_preflight.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,6 @@
class Cask::DSL::UninstallPreflight < Cask::DSL::Base
include Cask::Staged

def disable_accessibility_access
if MacOS.version >= :mavericks
@command.run!('/usr/bin/sqlite3',
:args => [
Cask.tcc_db,
"DELETE FROM access WHERE client='#{bundle_identifier}';",
],
:sudo => true)
else
opoo <<-EOS.undent
Accessibility access was enabled for #{@cask}, but it is not safe to disable
automatically on this version of OS X. See System Preferences.
EOS
end
end

def method_missing(method, *args)
Cask::Utils.method_missing_message(method, @cask.to_s, 'uninstall_preflight')
return nil
Expand Down
46 changes: 46 additions & 0 deletions lib/cask/installer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
require 'rubygems'
require 'cask/staged'

class Cask::Installer

# todo: it is unwise for Cask::Staged to be a module, when we are
# dealing with both staged and unstaged Casks here. This should
# either be a class which is only sometimes instantiated, or there
# should be explicit checks on whether staged state is valid in
# every method.
include Cask::Staged

PERSISTENT_METADATA_SUBDIRS = [ 'gpg' ]

def initialize(cask, command=Cask::SystemCommand)
Expand Down Expand Up @@ -51,6 +59,7 @@ def install(force=false)
download
extract_primary_container
install_artifacts
enable_accessibility_access
rescue StandardError => e
purge_versioned_files
raise e
Expand Down Expand Up @@ -172,8 +181,45 @@ def print_caveats
self.class.print_caveats(@cask)
end

# todo: logically could be in a separate class
def enable_accessibility_access
return unless @cask.accessibility_access
ohai 'Enabling accessibility access'
if MacOS.version >= :mavericks
@command.run!('/usr/bin/sqlite3',
:args => [
Cask.tcc_db,
"INSERT INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);",
],
:sudo => true)
else
@command.run!('/usr/bin/touch',
:args => [Cask.pre_mavericks_accessibility_dotfile],
:sudo => true)
end
end

def disable_accessibility_access
return unless @cask.accessibility_access
if MacOS.version >= :mavericks
ohai 'Disabling accessibility access'
@command.run!('/usr/bin/sqlite3',
:args => [
Cask.tcc_db,
"DELETE FROM access WHERE client='#{bundle_identifier}';",
],
:sudo => true)
else
opoo <<-EOS.undent
Accessibility access was enabled for #{@cask}, but it is not safe to disable
automatically on this version of OS X. See System Preferences.
EOS
end
end

def uninstall(force=false)
odebug "Cask::Installer.uninstall"
disable_accessibility_access
uninstall_artifacts
purge_versioned_files
purge_caskroom_path if force
Expand Down
4 changes: 2 additions & 2 deletions lib/cask/staged.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def info_plist(index = 0)
index = 0 if index == :first
index = 1 if index == :second
index = -1 if index == :last
staged_path.join(@cask.artifacts[:app].to_a.at(index).first, 'Contents', 'Info.plist')
@cask.staged_path.join(@cask.artifacts[:app].to_a.at(index).first, 'Contents', 'Info.plist')
end

def plist_exec(cmd)
Expand All @@ -15,6 +15,6 @@ def plist_set(key, value)
end

def bundle_identifier
plist_exec('Print CFBundleIdentifier')
plist_exec('Print CFBundleIdentifier').stdout.chomp
end
end
1 change: 1 addition & 0 deletions lib/cask/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def dumpcask
:conflicts_with,
:container,
:gpg,
:accessibility_access,
].each do |method|
printable_method = method.to_s
printable_method = "name" if printable_method == "full_name"
Expand Down
61 changes: 61 additions & 0 deletions test/cask/accessibility_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require 'test_helper'

# todo: this test should be named after the corresponding class, once
# that class is abstracted from installer.rb.
describe "Accessibility Access" do
before do
cask = Cask.load('with-accessibility-access')
@installer = Cask::Installer.new(cask, Cask::FakeSystemCommand)
end

describe "install" do
it "can enable accessibility access" do
MacOS.stubs(:version => OS::Mac::Version.new('10.9'))

@installer.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/sqlite3', Cask.tcc_db, %q{INSERT INTO access VALUES('kTCCServiceAccessibility','com.example.BasicCask',0,1,1,NULL);}]
)
shutup do
@installer.enable_accessibility_access
end
end

it "can enable accessibility access in OS X versions prior to Mavericks" do
MacOS.stubs(:version => OS::Mac::Version.new('10.8'))

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/touch', Cask.pre_mavericks_accessibility_dotfile]
)
shutup do
@installer.enable_accessibility_access
end
end
end

describe "uninstall" do
it "can disable accessibility access" do
MacOS.stubs(:version => OS::Mac::Version.new('10.9'))

@installer.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/sqlite3', Cask.tcc_db, %q{DELETE FROM access WHERE client='com.example.BasicCask';}]
)
shutup do
@installer.disable_accessibility_access
end
end
it "warns about disabling accessibility access on old OS X versions" do
MacOS.stubs(:version => OS::Mac::Version.new('10.8'))

@installer.stubs(:bundle_identifier => 'com.example.BasicCask')

out, err = capture_io do
@installer.disable_accessibility_access
end
err.must_match('Warning: Accessibility access was enabled for with-accessibility-access, but it is not safe to disable')
end
end
end
32 changes: 4 additions & 28 deletions test/cask/dsl/postflight_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,17 @@
end

it "can execute commands on the Info.plist file" do
@dsl.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/libexec/PlistBuddy', '-c', 'Print CFBundleIdentifier', @dsl.info_plist]
)
@dsl.plist_exec('Print CFBundleIdentifier')
end

it "can retrieve the bundle identifier for the primary app" do
Cask::FakeSystemCommand.stubs_command(
['/usr/libexec/PlistBuddy', '-c', 'Print CFBundleIdentifier', @dsl.info_plist],
'com.example.BasicCask'
)
@dsl.bundle_identifier.stdout.must_equal 'com.example.BasicCask'
end

it "can set a key in the Info.plist file" do
@dsl.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/libexec/PlistBuddy', '-c', 'Set :JVMOptions:JVMVersion 1.6+', @dsl.info_plist]
)
Expand All @@ -56,24 +52,4 @@
)
@dsl.suppress_move_to_applications :key => 'suppressMoveToApplications'
end

it "can enable accessibility access" do
MacOS.stubs(:version => OS::Mac::Version.new('10.9'))

@dsl.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/sqlite3', Cask.tcc_db, %q{INSERT INTO access VALUES('kTCCServiceAccessibility','com.example.BasicCask',0,1,1,NULL);}]
)
@dsl.enable_accessibility_access
end

it "can enable accessibility access in OS X versions prior to Mavericks" do
MacOS.stubs(:version => OS::Mac::Version.new('10.8'))

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/touch', Cask.pre_mavericks_accessibility_dotfile]
)
@dsl.enable_accessibility_access
end
end
22 changes: 0 additions & 22 deletions test/cask/dsl/uninstall_preflight_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,4 @@
cask = Cask.load('basic-cask')
@dsl = Cask::DSL::UninstallPreflight.new(cask, Cask::FakeSystemCommand)
end

it "can disable accessibility access" do
MacOS.stubs(:version => OS::Mac::Version.new('10.9'))

@dsl.stubs(:bundle_identifier => 'com.example.BasicCask')

Cask::FakeSystemCommand.expects_command(
['/usr/bin/sudo', '-E', '--', '/usr/bin/sqlite3', Cask.tcc_db, %q{DELETE FROM access WHERE client='com.example.BasicCask';}]
)
@dsl.disable_accessibility_access
end

it "warns about disabling accessibility access on old OS X versions" do
MacOS.stubs(:version => OS::Mac::Version.new('10.8'))

@dsl.stubs(:bundle_identifier => 'com.example.BasicCask')

out, err = capture_io do
@dsl.disable_accessibility_access
end
err.must_match('Warning: Accessibility access was enabled for basic-cask, but it is not safe to disable')
end
end
18 changes: 18 additions & 0 deletions test/cask/staged_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'test_helper'

# todo: this test should be named after the corresponding class, once
# that class is abstracted from installer.rb. It makes little sense
# to be invoking bundle_identifier off of the installer instance.
describe "Operations on staged Casks" do
describe "bundle ID" do
it "fetches the bundle ID from a staged cask" do
transmission_cask = Cask.load('local-transmission')
tr_installer = Cask::Installer.new(transmission_cask)

shutup do
tr_installer.install
end
tr_installer.bundle_identifier.must_equal('org.m0k.transmission')
end
end
end
Loading

0 comments on commit 5036750

Please sign in to comment.