Add context menu for inspecting elements. Fix #11.

This commit is contained in:
FelisCatus 2014-12-19 23:37:47 +08:00
parent b3fada8fac
commit 6d02c442fd
10 changed files with 230 additions and 10 deletions

View File

@ -807,6 +807,15 @@
"browserAction_titleExternalProxy": {
"message": "Note: The proxy settings are currently controlled by other app(s)."
},
"browserAction_titleInspect": {
"message": "[Inspect] $URL$",
"placeholders": {
"url": {
"content": "$1",
"example": "example.com/image.png"
}
}
},
"browserAction_defaultRuleDetails": {
"message": "(default)",
"description": "Representation of the default profile being selected on browserAction title."
@ -822,5 +831,17 @@
"browserAction_tempRulePrefix": {
"message": "(TEMP) ",
"description": "The prefix to indicate a temp rule on browserAction title. Should be very short."
},
"contextMenu_inspectPage": {
"message": "Inspect proxy used for this page"
},
"contextMenu_inspectFrame": {
"message": "Inspect proxy used for this Frame"
},
"contextMenu_inspectLink": {
"message": "Inspect proxy to be used if this Link is opened"
},
"contextMenu_inspectElement": {
"message": "Inspect proxy used for this Element"
}
}

View File

@ -807,6 +807,15 @@
"browserAction_titleExternalProxy": {
"message": "注意:其他应用正在控制当前代理设置。"
},
"browserAction_titleInspect": {
"message": "[检查] $URL$",
"placeholders": {
"url": {
"content": "$1",
"example": "example.com/image.png"
}
}
},
"browserAction_defaultRuleDetails": {
"message": "(默认)",
"description": "在图标悬停提示上表示选择了默认情景模式作为结果的文字。"
@ -822,5 +831,17 @@
"browserAction_tempRulePrefix": {
"message": "(临时) ",
"description": "在图标悬停提示上显示临时规则的前缀。文字应该非常短。"
},
"contextMenu_inspectPage": {
"message": "检查此页面使用的代理"
},
"contextMenu_inspectFrame": {
"message": "检查此[框架页面]使用的代理"
},
"contextMenu_inspectLink": {
"message": "检查此[链接目标]将会使用的代理"
},
"contextMenu_inspectElement": {
"message": "检查此[元素]使用的代理"
}
}

View File

@ -807,6 +807,15 @@
"browserAction_titleExternalProxy": {
"message": "注意:其他程式正在控制當前代理設置。"
},
"browserAction_titleInspect": {
"message": "[檢查] $URL$",
"placeholders": {
"url": {
"content": "$1",
"example": "example.com/image.png"
}
}
},
"browserAction_defaultRuleDetails": {
"message": "(默認)",
"description": "在圖標懸停提示上表示選擇了默認情景模式作爲結果的文字。"
@ -822,5 +831,17 @@
"browserAction_tempRulePrefix": {
"message": "(臨時) ",
"description": "在圖標懸停提示上顯示臨時規則的前綴。文字應該非常短。"
},
"contextMenu_inspectPage": {
"message": "檢查此頁面使用的代理"
},
"contextMenu_inspectFrame": {
"message": "檢查此[框架頁面]使用的代理"
},
"contextMenu_inspectLink": {
"message": "檢查此[連結目標]將會使用的代理"
},
"contextMenu_inspectElement": {
"message": "檢查此[元素]使用的代理"
}
}

View File

@ -807,6 +807,15 @@
"browserAction_titleExternalProxy": {
"message": "注意:其他應用正在控制當前代理設定。"
},
"browserAction_titleInspect": {
"message": "[檢查] $URL$",
"placeholders": {
"url": {
"content": "$1",
"example": "example.com/image.png"
}
}
},
"browserAction_defaultRuleDetails": {
"message": "(默認)",
"description": "在圖示懸停提示上表示選擇了默認情景模式作為結果的文字。"
@ -822,5 +831,17 @@
"browserAction_tempRulePrefix": {
"message": "(臨時) ",
"description": "在圖示懸停提示上顯示臨時規則的字首。文字應該非常短。"
},
"contextMenu_inspectPage": {
"message": "檢查此頁面使用的代理"
},
"contextMenu_inspectFrame": {
"message": "檢查此[框架頁面]使用的代理"
},
"contextMenu_inspectLink": {
"message": "檢查此[連結目標]將會使用的代理"
},
"contextMenu_inspectElement": {
"message": "檢查此[元素]使用的代理"
}
}

View File

@ -102,14 +102,22 @@ actionForUrl = (url) ->
if not details
details = options.printProfile(current)
icon =
if profile.name == current.name and options.isCurrentProfileStatic()
if direct
drawIcon(options.profile('direct').color, profile.color)
else
drawIcon(profile.color)
resultColor = profile.color
profileColor = current.color
icon = null
if profile.name == current.name and options.isCurrentProfileStatic()
if direct
resultColor = options.profile('direct').color
profileColor = profile.color
else
drawIcon(profile.color, current.color)
resultColor = profileColor = profile.color
icon = drawIcon(profile.color)
else
resultColor = profile.color
profileColor = current.color
icon ?= drawIcon(resultColor, profileColor)
return {
title: chrome.i18n.getMessage('browserAction_titleWithResult', [
currentName
@ -117,6 +125,8 @@ actionForUrl = (url) ->
details
])
icon: icon
resultColor: resultColor
profileColor: profileColor
}
@ -133,6 +143,32 @@ if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId
tabs = new OmegaTargetCurrent.ChromeTabs(actionForUrl)
tabs.watch()
inspect = new OmegaTargetCurrent.Inspect (url, tab) ->
if url == tab.url
options.clearBadge()
tabs.processTab(tab)
state.remove('inspectUrl')
return
state.set({inspectUrl: url})
actionForUrl(url).then (action) ->
parsedUrl = OmegaTargetCurrent.Url.parse(url)
if parsedUrl.hostname == OmegaTargetCurrent.Url.parse(tab.url).hostname
urlDisp = parsedUrl.path
else
urlDisp = parsedUrl.hostname
title = chrome.i18n.getMessage('browserAction_titleInspect', urlDisp) + '\n'
title += action.title
chrome.browserAction.setTitle(title: title, tabId: tab.id)
tabs.setTabBadge(tab, {
text: '#'
color: action.resultColor
})
inspect.register()
options.setProxyNotControllable(null)
timeout = null

View File

@ -4,6 +4,7 @@ module.exports =
ChromeTabs: require('./src/tabs')
SwitchySharp: require('./src/switchysharp')
ExternalApi: require('./src/external_api.coffee')
Inspect: require('./src/inspect')
Url: require('url')
for name, value of require('omega-target')

View File

@ -101,12 +101,25 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) ->
setDefaultProfile: (profileName, defaultProfileName) ->
callBackground('setDefaultProfile', profileName, defaultProfileName)
getActivePageInfo: ->
# First, try to clear badges on opening the popup.
callBackground('clearBadge')
clearBadge = true
d = $q['defer']()
chrome.tabs.query {active: true, lastFocusedWindow: true}, (tabs) ->
d.resolve(tabs[0]?.url)
if not tabs[0]?.url
d.resolve(undefined)
return
getBadge = $q['defer']()
chrome.browserAction.getBadgeText {tabId: tabs[0]?.id}, (result) ->
getBadge.resolve(result)
$q.all([getBadge.promise, omegaTarget.state('inspectUrl')
]).then ([badge, url]) ->
if badge != '#' || not url
d.resolve(tabs[0]?.url)
else
clearBadge = false
d.resolve(url)
return d.promise.then (url) ->
# First, try to clear badges on opening the popup.
callBackground('clearBadge') if clearBadge
return null if not url or isChromeUrl(url)
urlParser.href = url
domain = urlParser.hostname

View File

@ -29,6 +29,8 @@
"storage",
"webRequest",
"webRequestBlocking",
"contextMenus",
"http://*/*",
"https://*/*",
"ftp://*/*",

View File

@ -0,0 +1,70 @@
OmegaTarget = require('omega-target')
OmegaPac = OmegaTarget.OmegaPac
Promise = OmegaTarget.Promise
module.exports = class Inspect
constructor: (@onInspect) ->
register: ->
# We don't need this API. However its presence indicates that Chrome >= 35,
# which provides the menuItemId we need in contextMenu callback.
# https://developer.chrome.com/extensions/contextMenus
return unless chrome.i18n.getUILanguage?
webResource = [
"http://*/*"
"https://*/*"
"ftp://*/*"
]
chrome.contextMenus.create({
id: 'inspectPage'
title: chrome.i18n.getMessage('contextMenu_inspectPage')
contexts: ['page']
onclick: @inspect.bind(this)
documentUrlPatterns: webResource
})
chrome.contextMenus.create({
id: 'inspectFrame'
title: chrome.i18n.getMessage('contextMenu_inspectFrame')
contexts: ['frame']
onclick: @inspect.bind(this)
documentUrlPatterns: webResource
})
chrome.contextMenus.create({
id: 'inspectLink'
title: chrome.i18n.getMessage('contextMenu_inspectLink')
contexts: ['link']
onclick: @inspect.bind(this)
targetUrlPatterns: webResource
})
chrome.contextMenus.create({
id: 'inspectElement'
title: chrome.i18n.getMessage('contextMenu_inspectElement')
contexts: [
'image'
'video'
'audio'
]
onclick: @inspect.bind(this)
targetUrlPatterns: webResource
})
propForMenuItem:
'inspectPage': 'pageUrl'
'inspectFrame': 'frameUrl'
'inspectLink': 'linkUrl'
'inspectElement': 'srcUrl'
inspect: (info, tab) ->
return unless info.menuItemId
url = info[@propForMenuItem[info.menuItemId]]
if not url and info.menuItemId == 'inspectPage'
url = tab.url
return unless url
@onInspect(url, tab)

View File

@ -1,6 +1,7 @@
class ChromeTabs
_dirtyTabs: {}
_defaultAction: null
_badgeTab: null
constructor: (@actionForUrl) -> return
@ -34,6 +35,10 @@ class ChromeTabs
@processTab(tab, changeInfo)
processTab: (tab, changeInfo) ->
if @_badgeTab
for own id of @_badgeTab
try chrome.browserAction.setBadgeText(text: '', tabId: id)
@_badgeTab = null
if not tab.url? or tab.url.indexOf("chrome") == 0
chrome.browserAction.setTitle(title: @_defaultAction.title, tabId: tab.id)
@clearIcon tab.id
@ -42,6 +47,15 @@ class ChromeTabs
@setIcon(action.icon, tab.id)
chrome.browserAction.setTitle(title: action.title, tabId: tab.id)
setTabBadge: (tab, badge) ->
@_badgeTab ?= {}
@_badgeTab[tab.id] = true
chrome.browserAction.setBadgeText(text: badge.text, tabId: tab.id)
chrome.browserAction.setBadgeBackgroundColor(
color: badge.color
tabId: tab.id
)
setIcon: (icon, tabId) ->
if tabId?
chrome.browserAction.setIcon({