As you already noticed Experience Editor utilizes SPEAK, but Content Editor "is not there yet".
I am not sure whether you can have single code to handle both locations.
I would go partially SPEAK and Sheer but it depends what you want to achieve.
In Experience Editor you can extend front-end pipeline written in SPEAK
(/sitecore/client/Applications/ExperienceEditor/Pipelines/Save
):

This how you normally ask user in Experience Editor via SPEAK to confirm something. (This is an example of confirm before you navigate somewhere else and you have unsaved changes)
experienceEditor.Dialogs.confirm(TranslationUtil.translateText(TranslationUtil.keys.The_item_has_been_modified), function (isOk) {
if (!isOk) {
if (onCloseCallback) {
return onCloseCallback(isOk);
}
return null;
}
ExperienceEditorContext.instance.disableRedirection = disableRedirection;
Sitecore.Commands.Save.execute(ExperienceEditorContext.instance);
experienceEditor.Common.addOneTimeEvent(function () {
return ExperienceEditorContext.isContentSaved;
}, function () {
if (onCloseCallback) {
return onCloseCallback(isOk);
}
}, 100, this);
return null;
});
Regarding Sheer, I suppose you already know how to do it.
If you have any additional questions, ask I will try to answer.